mirror of
https://github.com/esphome/esphome.git
synced 2025-11-03 16:41:50 +00:00
Compare commits
1 Commits
2024.5.0b3
...
jesserockz
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f96aff5107 |
16
.github/actions/build-image/action.yaml
vendored
16
.github/actions/build-image/action.yaml
vendored
@@ -57,6 +57,14 @@ runs:
|
||||
digest="${{ steps.build-ghcr.outputs.digest }}"
|
||||
touch "/tmp/digests/${{ inputs.target }}/ghcr/${digest#sha256:}"
|
||||
|
||||
- name: Upload ghcr digest
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
name: digests-${{ inputs.target }}-ghcr
|
||||
path: /tmp/digests/${{ inputs.target }}/ghcr/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Build and push to dockerhub by digest
|
||||
id: build-dockerhub
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
@@ -79,3 +87,11 @@ runs:
|
||||
mkdir -p /tmp/digests/${{ inputs.target }}/dockerhub
|
||||
digest="${{ steps.build-dockerhub.outputs.digest }}"
|
||||
touch "/tmp/digests/${{ inputs.target }}/dockerhub/${digest#sha256:}"
|
||||
|
||||
- name: Upload dockerhub digest
|
||||
uses: actions/upload-artifact@v3.1.3
|
||||
with:
|
||||
name: digests-${{ inputs.target }}-dockerhub
|
||||
path: /tmp/digests/${{ inputs.target }}/dockerhub/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
2
.github/workflows/ci-api-proto.yml
vendored
2
.github/workflows/ci-api-proto.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
|
||||
2
.github/workflows/ci-docker.yml
vendored
2
.github/workflows/ci-docker.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
arch: [amd64, armv7, aarch64]
|
||||
build_type: ["ha-addon", "docker", "lint"]
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.5
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
|
||||
32
.github/workflows/ci.yml
vendored
32
.github/workflows/ci.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
cache-key: ${{ steps.cache-key.outputs.key }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Generate cache-key
|
||||
id: cache-key
|
||||
run: echo key="${{ hashFiles('requirements.txt', 'requirements_optional.txt', 'requirements_test.txt') }}" >> $GITHUB_OUTPUT
|
||||
@@ -66,7 +66,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -87,7 +87,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -108,7 +108,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -150,7 +150,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -199,7 +199,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -229,7 +229,7 @@ jobs:
|
||||
- common
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -254,7 +254,7 @@ jobs:
|
||||
matrix: ${{ steps.set-matrix.outputs.matrix }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Find all YAML test files
|
||||
id: set-matrix
|
||||
run: echo "matrix=$(ls tests/test*.yaml | jq -R -s -c 'split("\n")[:-1]')" >> $GITHUB_OUTPUT
|
||||
@@ -271,7 +271,7 @@ jobs:
|
||||
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -303,7 +303,7 @@ jobs:
|
||||
file: ${{ fromJson(needs.compile-tests-list.outputs.matrix) }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -358,7 +358,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -402,7 +402,7 @@ jobs:
|
||||
count: ${{ steps.list-components.outputs.count }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
with:
|
||||
# Fetch enough history so `git merge-base refs/remotes/origin/dev HEAD` works.
|
||||
fetch-depth: 500
|
||||
@@ -450,7 +450,7 @@ jobs:
|
||||
run: sudo apt-get install libsodium-dev
|
||||
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
@@ -476,7 +476,7 @@ jobs:
|
||||
matrix: ${{ steps.split.outputs.components }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Split components into 20 groups
|
||||
id: split
|
||||
run: |
|
||||
@@ -504,7 +504,7 @@ jobs:
|
||||
run: sudo apt-get install libsodium-dev
|
||||
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Restore Python
|
||||
uses: ./.github/actions/restore-python
|
||||
with:
|
||||
|
||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
tag: ${{ steps.tag.outputs.tag }}
|
||||
branch_build: ${{ steps.tag.outputs.branch_build }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.5
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Get tag
|
||||
id: tag
|
||||
# yamllint disable rule:line-length
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
contents: read
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.5
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
@@ -81,7 +81,7 @@ jobs:
|
||||
- linux/arm/v7
|
||||
- linux/arm64
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.5
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5.1.0
|
||||
with:
|
||||
@@ -132,19 +132,6 @@ jobs:
|
||||
suffix: lint
|
||||
version: ${{ needs.init.outputs.tag }}
|
||||
|
||||
- name: Sanitize platform name
|
||||
id: sanitize
|
||||
run: |
|
||||
echo "${{ matrix.platform }}" | sed 's|/|-|g' > /tmp/platform
|
||||
echo name=$(cat /tmp/platform) >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Upload digests
|
||||
uses: actions/upload-artifact@v4.3.3
|
||||
with:
|
||||
name: digests-${{ steps.sanitize.outputs.name }}
|
||||
path: /tmp/digests
|
||||
retention-days: 1
|
||||
|
||||
deploy-manifest:
|
||||
name: Publish ESPHome ${{ matrix.image.title }} to ${{ matrix.registry }}
|
||||
runs-on: ubuntu-latest
|
||||
@@ -172,15 +159,12 @@ jobs:
|
||||
- ghcr
|
||||
- dockerhub
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.5
|
||||
|
||||
- uses: actions/checkout@v4.1.1
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4.1.7
|
||||
uses: actions/download-artifact@v3.0.2
|
||||
with:
|
||||
pattern: digests-*
|
||||
name: digests-${{ matrix.image.target }}-${{ matrix.registry }}
|
||||
path: /tmp/digests
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3.3.0
|
||||
|
||||
@@ -211,7 +195,7 @@ jobs:
|
||||
done
|
||||
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests/${{ matrix.image.target }}/${{ matrix.registry }}
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -Rcnr 'inputs | . / "," | map("-t " + .) | join(" ")' <<< "${{ steps.tags.outputs.tags}}") \
|
||||
$(printf '${{ steps.tags.outputs.image }}@sha256:%s ' *)
|
||||
|
||||
4
.github/workflows/sync-device-classes.yml
vendored
4
.github/workflows/sync-device-classes.yml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
if: github.repository == 'esphome/esphome'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
|
||||
- name: Checkout Home Assistant
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
with:
|
||||
repository: home-assistant/core
|
||||
path: lib/home-assistant
|
||||
|
||||
2
.github/workflows/yaml-lint.yml
vendored
2
.github/workflows/yaml-lint.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v4.1.5
|
||||
uses: actions/checkout@v4.1.1
|
||||
- name: Run yamllint
|
||||
uses: frenck/action-yamllint@v1.5.0
|
||||
with:
|
||||
|
||||
@@ -63,10 +63,7 @@ esphome/components/bme280_base/* @esphome/core
|
||||
esphome/components/bme280_spi/* @apbodrov
|
||||
esphome/components/bme680_bsec/* @trvrnrth
|
||||
esphome/components/bmi160/* @flaviut
|
||||
esphome/components/bmp3xx/* @latonita
|
||||
esphome/components/bmp3xx_base/* @latonita @martgras
|
||||
esphome/components/bmp3xx_i2c/* @latonita
|
||||
esphome/components/bmp3xx_spi/* @latonita
|
||||
esphome/components/bmp3xx/* @martgras
|
||||
esphome/components/bmp581/* @kahrendt
|
||||
esphome/components/bp1658cj/* @Cossid
|
||||
esphome/components/bp5758d/* @Cossid
|
||||
@@ -245,7 +242,7 @@ esphome/components/mpl3115a2/* @kbickar
|
||||
esphome/components/mpu6886/* @fabaff
|
||||
esphome/components/ms8607/* @e28eta
|
||||
esphome/components/network/* @esphome/core
|
||||
esphome/components/nextion/* @edwardtfn @senexcrenshaw
|
||||
esphome/components/nextion/* @senexcrenshaw
|
||||
esphome/components/nextion/binary_sensor/* @senexcrenshaw
|
||||
esphome/components/nextion/sensor/* @senexcrenshaw
|
||||
esphome/components/nextion/switch/* @senexcrenshaw
|
||||
|
||||
@@ -19,7 +19,6 @@ from esphome.const import (
|
||||
CONF_RESET_PIN,
|
||||
CONF_REVERSE_ACTIVE_ENERGY,
|
||||
CONF_VOLTAGE,
|
||||
CONF_VOLTAGE_GAIN,
|
||||
DEVICE_CLASS_APPARENT_POWER,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
@@ -48,6 +47,7 @@ CONF_CURRENT_GAIN = "current_gain"
|
||||
CONF_IRQ0_PIN = "irq0_pin"
|
||||
CONF_IRQ1_PIN = "irq1_pin"
|
||||
CONF_POWER_GAIN = "power_gain"
|
||||
CONF_VOLTAGE_GAIN = "voltage_gain"
|
||||
|
||||
CONF_NEUTRAL = "neutral"
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_IRQ_PIN,
|
||||
CONF_VOLTAGE,
|
||||
CONF_FREQUENCY,
|
||||
CONF_VOLTAGE_GAIN,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_APPARENT_POWER,
|
||||
DEVICE_CLASS_POWER,
|
||||
@@ -37,6 +36,7 @@ CONF_POWER_FACTOR_B = "power_factor_b"
|
||||
CONF_VOLTAGE_PGA_GAIN = "voltage_pga_gain"
|
||||
CONF_CURRENT_PGA_GAIN_A = "current_pga_gain_a"
|
||||
CONF_CURRENT_PGA_GAIN_B = "current_pga_gain_b"
|
||||
CONF_VOLTAGE_GAIN = "voltage_gain"
|
||||
CONF_CURRENT_GAIN_A = "current_gain_a"
|
||||
CONF_CURRENT_GAIN_B = "current_gain_b"
|
||||
CONF_ACTIVE_POWER_GAIN_A = "active_power_gain_a"
|
||||
|
||||
@@ -54,6 +54,7 @@ FAST_FILTER = {
|
||||
"LSB10": 7,
|
||||
}
|
||||
|
||||
CONF_ANGLE = "angle"
|
||||
CONF_RAW_ANGLE = "raw_angle"
|
||||
CONF_RAW_POSITION = "raw_position"
|
||||
CONF_WATCHDOG = "watchdog"
|
||||
|
||||
@@ -11,7 +11,6 @@ from esphome.const import (
|
||||
CONF_MAGNITUDE,
|
||||
CONF_STATUS,
|
||||
CONF_POSITION,
|
||||
CONF_ANGLE,
|
||||
)
|
||||
from .. import as5600_ns, AS5600Component
|
||||
|
||||
@@ -20,6 +19,7 @@ DEPENDENCIES = ["as5600"]
|
||||
|
||||
AS5600Sensor = as5600_ns.class_("AS5600Sensor", sensor.Sensor, cg.PollingComponent)
|
||||
|
||||
CONF_ANGLE = "angle"
|
||||
CONF_RAW_ANGLE = "raw_angle"
|
||||
CONF_RAW_POSITION = "raw_position"
|
||||
CONF_WATCHDOG = "watchdog"
|
||||
|
||||
@@ -22,6 +22,7 @@ CONF_AT581X_ID = "at581x_id"
|
||||
|
||||
|
||||
CONF_SENSING_DISTANCE = "sensing_distance"
|
||||
CONF_SENSITIVITY = "sensitivity"
|
||||
CONF_POWERON_SELFCHECK_TIME = "poweron_selfcheck_time"
|
||||
CONF_PROTECT_TIME = "protect_time"
|
||||
CONF_TRIGGER_BASE = "trigger_base"
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_ENERGY,
|
||||
CONF_EXTERNAL_TEMPERATURE,
|
||||
CONF_ID,
|
||||
CONF_INTERNAL_TEMPERATURE,
|
||||
CONF_POWER,
|
||||
CONF_VOLTAGE,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
@@ -25,6 +24,7 @@ from esphome.const import (
|
||||
|
||||
DEPENDENCIES = ["uart"]
|
||||
|
||||
CONF_INTERNAL_TEMPERATURE = "internal_temperature"
|
||||
|
||||
bl0940_ns = cg.esphome_ns.namespace("bl0940")
|
||||
BL0940 = bl0940_ns.class_("BL0940", cg.PollingComponent, uart.UARTDevice)
|
||||
|
||||
@@ -1,108 +1 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
CONF_HUMIDITY,
|
||||
CONF_ID,
|
||||
CONF_IIR_FILTER,
|
||||
CONF_OVERSAMPLING,
|
||||
CONF_PRESSURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_HECTOPASCAL,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
|
||||
bme280_ns = cg.esphome_ns.namespace("bme280_base")
|
||||
BME280Oversampling = bme280_ns.enum("BME280Oversampling")
|
||||
OVERSAMPLING_OPTIONS = {
|
||||
"NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE,
|
||||
"1X": BME280Oversampling.BME280_OVERSAMPLING_1X,
|
||||
"2X": BME280Oversampling.BME280_OVERSAMPLING_2X,
|
||||
"4X": BME280Oversampling.BME280_OVERSAMPLING_4X,
|
||||
"8X": BME280Oversampling.BME280_OVERSAMPLING_8X,
|
||||
"16X": BME280Oversampling.BME280_OVERSAMPLING_16X,
|
||||
}
|
||||
|
||||
BME280IIRFilter = bme280_ns.enum("BME280IIRFilter")
|
||||
IIR_FILTER_OPTIONS = {
|
||||
"OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF,
|
||||
"2X": BME280IIRFilter.BME280_IIR_FILTER_2X,
|
||||
"4X": BME280IIRFilter.BME280_IIR_FILTER_4X,
|
||||
"8X": BME280IIRFilter.BME280_IIR_FILTER_8X,
|
||||
"16X": BME280IIRFilter.BME280_IIR_FILTER_16X,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA_BASE = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_HUMIDITY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
|
||||
IIR_FILTER_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
).extend(cv.polling_component_schema("60s"))
|
||||
|
||||
|
||||
async def to_code_base(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
if temperature_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temperature_config)
|
||||
cg.add(var.set_temperature_sensor(sens))
|
||||
cg.add(var.set_temperature_oversampling(temperature_config[CONF_OVERSAMPLING]))
|
||||
|
||||
if pressure_config := config.get(CONF_PRESSURE):
|
||||
sens = await sensor.new_sensor(pressure_config)
|
||||
cg.add(var.set_pressure_sensor(sens))
|
||||
cg.add(var.set_pressure_oversampling(pressure_config[CONF_OVERSAMPLING]))
|
||||
|
||||
if humidity_config := config.get(CONF_HUMIDITY):
|
||||
sens = await sensor.new_sensor(humidity_config)
|
||||
cg.add(var.set_humidity_sensor(sens))
|
||||
cg.add(var.set_humidity_oversampling(humidity_config[CONF_OVERSAMPLING]))
|
||||
|
||||
cg.add(var.set_iir_filter(config[CONF_IIR_FILTER]))
|
||||
|
||||
return var
|
||||
|
||||
106
esphome/components/bme280_base/sensor.py
Normal file
106
esphome/components/bme280_base/sensor.py
Normal file
@@ -0,0 +1,106 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
CONF_HUMIDITY,
|
||||
CONF_ID,
|
||||
CONF_IIR_FILTER,
|
||||
CONF_OVERSAMPLING,
|
||||
CONF_PRESSURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_HECTOPASCAL,
|
||||
UNIT_PERCENT,
|
||||
)
|
||||
|
||||
bme280_ns = cg.esphome_ns.namespace("bme280_base")
|
||||
BME280Oversampling = bme280_ns.enum("BME280Oversampling")
|
||||
OVERSAMPLING_OPTIONS = {
|
||||
"NONE": BME280Oversampling.BME280_OVERSAMPLING_NONE,
|
||||
"1X": BME280Oversampling.BME280_OVERSAMPLING_1X,
|
||||
"2X": BME280Oversampling.BME280_OVERSAMPLING_2X,
|
||||
"4X": BME280Oversampling.BME280_OVERSAMPLING_4X,
|
||||
"8X": BME280Oversampling.BME280_OVERSAMPLING_8X,
|
||||
"16X": BME280Oversampling.BME280_OVERSAMPLING_16X,
|
||||
}
|
||||
|
||||
BME280IIRFilter = bme280_ns.enum("BME280IIRFilter")
|
||||
IIR_FILTER_OPTIONS = {
|
||||
"OFF": BME280IIRFilter.BME280_IIR_FILTER_OFF,
|
||||
"2X": BME280IIRFilter.BME280_IIR_FILTER_2X,
|
||||
"4X": BME280IIRFilter.BME280_IIR_FILTER_4X,
|
||||
"8X": BME280IIRFilter.BME280_IIR_FILTER_8X,
|
||||
"16X": BME280IIRFilter.BME280_IIR_FILTER_16X,
|
||||
}
|
||||
|
||||
CONFIG_SCHEMA_BASE = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_PERCENT,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_HUMIDITY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
|
||||
IIR_FILTER_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
).extend(cv.polling_component_schema("60s"))
|
||||
|
||||
|
||||
async def to_code(config, func=None):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
if func is not None:
|
||||
await func(var, config)
|
||||
|
||||
if temperature_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temperature_config)
|
||||
cg.add(var.set_temperature_sensor(sens))
|
||||
cg.add(var.set_temperature_oversampling(temperature_config[CONF_OVERSAMPLING]))
|
||||
|
||||
if pressure_config := config.get(CONF_PRESSURE):
|
||||
sens = await sensor.new_sensor(pressure_config)
|
||||
cg.add(var.set_pressure_sensor(sens))
|
||||
cg.add(var.set_pressure_oversampling(pressure_config[CONF_OVERSAMPLING]))
|
||||
|
||||
if humidity_config := config.get(CONF_HUMIDITY):
|
||||
sens = await sensor.new_sensor(humidity_config)
|
||||
cg.add(var.set_humidity_sensor(sens))
|
||||
cg.add(var.set_humidity_oversampling(humidity_config[CONF_OVERSAMPLING]))
|
||||
|
||||
cg.add(var.set_iir_filter(config[CONF_IIR_FILTER]))
|
||||
@@ -1,10 +1,9 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from ..bme280_base import to_code_base, CONFIG_SCHEMA_BASE
|
||||
from ..bme280_base.sensor import to_code as to_code_base, cv, CONFIG_SCHEMA_BASE
|
||||
|
||||
AUTO_LOAD = ["bme280_base"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
AUTO_LOAD = ["bme280_base"]
|
||||
|
||||
bme280_ns = cg.esphome_ns.namespace("bme280_i2c")
|
||||
BME280I2CComponent = bme280_ns.class_(
|
||||
@@ -17,5 +16,4 @@ CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await to_code_base(config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
await to_code_base(config, func=i2c.register_i2c_device)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@apbodrov"]
|
||||
|
||||
@@ -4,19 +4,19 @@
|
||||
#include "bme280_spi.h"
|
||||
#include <esphome/components/bme280_base/bme280_base.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace bme280_spi {
|
||||
|
||||
uint8_t set_bit(uint8_t num, int position) {
|
||||
int set_bit(uint8_t num, int position) {
|
||||
int mask = 1 << position;
|
||||
return num | mask;
|
||||
}
|
||||
|
||||
uint8_t clear_bit(uint8_t num, int position) {
|
||||
int clear_bit(uint8_t num, int position) {
|
||||
int mask = 1 << position;
|
||||
return num & ~mask;
|
||||
}
|
||||
|
||||
namespace esphome {
|
||||
namespace bme280_spi {
|
||||
|
||||
void BME280SPIComponent::setup() {
|
||||
this->spi_setup();
|
||||
BME280Component::setup();
|
||||
@@ -30,33 +30,34 @@ void BME280SPIComponent::setup() {
|
||||
|
||||
bool BME280SPIComponent::read_byte(uint8_t a_register, uint8_t *data) {
|
||||
this->enable();
|
||||
this->transfer_byte(set_bit(a_register, 7));
|
||||
*data = this->transfer_byte(0);
|
||||
// cause: *data = this->delegate_->transfer(tmp) doesnt work
|
||||
this->delegate_->transfer(set_bit(a_register, 7));
|
||||
*data = this->delegate_->transfer(0);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BME280SPIComponent::write_byte(uint8_t a_register, uint8_t data) {
|
||||
this->enable();
|
||||
this->transfer_byte(clear_bit(a_register, 7));
|
||||
this->transfer_byte(data);
|
||||
this->delegate_->transfer(clear_bit(a_register, 7));
|
||||
this->delegate_->transfer(data);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BME280SPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) {
|
||||
this->enable();
|
||||
this->transfer_byte(set_bit(a_register, 7));
|
||||
this->read_array(data, len);
|
||||
this->delegate_->transfer(set_bit(a_register, 7));
|
||||
this->delegate_->read_array(data, len);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BME280SPIComponent::read_byte_16(uint8_t a_register, uint16_t *data) {
|
||||
this->enable();
|
||||
this->transfer_byte(set_bit(a_register, 7));
|
||||
((uint8_t *) data)[1] = this->transfer_byte(0);
|
||||
((uint8_t *) data)[0] = this->transfer_byte(0);
|
||||
this->delegate_->transfer(set_bit(a_register, 7));
|
||||
((uint8_t *) data)[1] = this->delegate_->transfer(0);
|
||||
((uint8_t *) data)[0] = this->delegate_->transfer(0);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import spi
|
||||
from ..bme280_base import to_code_base, CONFIG_SCHEMA_BASE
|
||||
from esphome.components.bme280_base.sensor import (
|
||||
to_code as to_code_base,
|
||||
cv,
|
||||
CONFIG_SCHEMA_BASE,
|
||||
)
|
||||
|
||||
AUTO_LOAD = ["bme280_base"]
|
||||
CODEOWNERS = ["@apbodrov"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
AUTO_LOAD = ["bme280_base"]
|
||||
|
||||
|
||||
bme280_spi_ns = cg.esphome_ns.namespace("bme280_spi")
|
||||
@@ -19,5 +21,4 @@ CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend(
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await to_code_base(config)
|
||||
await spi.register_spi_device(var, config)
|
||||
await to_code_base(config, func=spi.register_spi_device)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, esp32
|
||||
from esphome.const import CONF_ID, CONF_TEMPERATURE_OFFSET
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ["@trvrnrth"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
@@ -9,6 +9,7 @@ AUTO_LOAD = ["sensor", "text_sensor"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_BME680_BSEC_ID = "bme680_bsec_id"
|
||||
CONF_TEMPERATURE_OFFSET = "temperature_offset"
|
||||
CONF_IAQ_MODE = "iaq_mode"
|
||||
CONF_SUPPLY_VOLTAGE = "supply_voltage"
|
||||
CONF_SAMPLE_RATE = "sample_rate"
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
http://github.com/MartinL1/BMP388_DEV
|
||||
*/
|
||||
|
||||
#include "bmp3xx_base.h"
|
||||
#include "bmp3xx.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_base {
|
||||
namespace bmp3xx {
|
||||
|
||||
static const char *const TAG = "bmp3xx.sensor";
|
||||
|
||||
@@ -150,6 +150,7 @@ void BMP3XXComponent::setup() {
|
||||
void BMP3XXComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "BMP3XX:");
|
||||
ESP_LOGCONFIG(TAG, " Type: %s (0x%X)", LOG_STR_ARG(chip_type_to_str(this->chip_id_.reg)), this->chip_id_.reg);
|
||||
LOG_I2C_DEVICE(this);
|
||||
switch (this->error_code_) {
|
||||
case NONE:
|
||||
break;
|
||||
@@ -385,5 +386,5 @@ float BMP3XXComponent::bmp388_compensate_pressure_(float uncomp_press, float t_l
|
||||
return partial_out1 + partial_out2 + partial_data4;
|
||||
}
|
||||
|
||||
} // namespace bmp3xx_base
|
||||
} // namespace bmp3xx
|
||||
} // namespace esphome
|
||||
@@ -9,9 +9,10 @@
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_base {
|
||||
namespace bmp3xx {
|
||||
|
||||
static const uint8_t BMP388_ID = 0x50; // The BMP388 device ID
|
||||
static const uint8_t BMP390_ID = 0x60; // The BMP390 device ID
|
||||
@@ -68,8 +69,8 @@ enum IIRFilter {
|
||||
IIR_FILTER_128 = 0x07
|
||||
};
|
||||
|
||||
/// This class implements support for the BMP3XX Temperature+Pressure sensor.
|
||||
class BMP3XXComponent : public PollingComponent {
|
||||
/// This class implements support for the BMP3XX Temperature+Pressure i2c sensor.
|
||||
class BMP3XXComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
@@ -230,13 +231,7 @@ class BMP3XXComponent : public PollingComponent {
|
||||
float bmp388_compensate_temperature_(float uncomp_temp);
|
||||
// Bosch pressure compensation function
|
||||
float bmp388_compensate_pressure_(float uncomp_press, float t_lin);
|
||||
|
||||
// interface specific functions
|
||||
virtual bool read_byte(uint8_t a_register, uint8_t *data) = 0;
|
||||
virtual bool write_byte(uint8_t a_register, uint8_t data) = 0;
|
||||
virtual bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0;
|
||||
virtual bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) = 0;
|
||||
};
|
||||
|
||||
} // namespace bmp3xx_base
|
||||
} // namespace bmp3xx
|
||||
} // namespace esphome
|
||||
@@ -1,7 +1,102 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
|
||||
CODEOWNERS = ["@latonita"]
|
||||
|
||||
CONFIG_SCHEMA = CONFIG_SCHEMA = cv.invalid(
|
||||
"The bmp3xx sensor component has been renamed to bmp3xx_i2c."
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_IIR_FILTER,
|
||||
CONF_OVERSAMPLING,
|
||||
CONF_PRESSURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_HECTOPASCAL,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@martgras"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx")
|
||||
Oversampling = bmp3xx_ns.enum("Oversampling")
|
||||
OVERSAMPLING_OPTIONS = {
|
||||
"NONE": Oversampling.OVERSAMPLING_NONE,
|
||||
"2X": Oversampling.OVERSAMPLING_X2,
|
||||
"4X": Oversampling.OVERSAMPLING_X4,
|
||||
"8X": Oversampling.OVERSAMPLING_X8,
|
||||
"16X": Oversampling.OVERSAMPLING_X16,
|
||||
"32X": Oversampling.OVERSAMPLING_X32,
|
||||
}
|
||||
|
||||
IIRFilter = bmp3xx_ns.enum("IIRFilter")
|
||||
IIR_FILTER_OPTIONS = {
|
||||
"OFF": IIRFilter.IIR_FILTER_OFF,
|
||||
"2X": IIRFilter.IIR_FILTER_2,
|
||||
"4X": IIRFilter.IIR_FILTER_4,
|
||||
"8X": IIRFilter.IIR_FILTER_8,
|
||||
"16X": IIRFilter.IIR_FILTER_16,
|
||||
"32X": IIRFilter.IIR_FILTER_32,
|
||||
"64X": IIRFilter.IIR_FILTER_64,
|
||||
"128X": IIRFilter.IIR_FILTER_128,
|
||||
}
|
||||
|
||||
BMP3XXComponent = bmp3xx_ns.class_(
|
||||
"BMP3XXComponent", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(BMP3XXComponent),
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="2X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
|
||||
IIR_FILTER_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x77))
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER]))
|
||||
if temperature_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temperature_config)
|
||||
cg.add(var.set_temperature_sensor(sens))
|
||||
cg.add(
|
||||
var.set_temperature_oversampling_config(
|
||||
temperature_config[CONF_OVERSAMPLING]
|
||||
)
|
||||
)
|
||||
|
||||
if pressure_config := config.get(CONF_PRESSURE):
|
||||
sens = await sensor.new_sensor(pressure_config)
|
||||
cg.add(var.set_pressure_sensor(sens))
|
||||
cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING]))
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_IIR_FILTER,
|
||||
CONF_OVERSAMPLING,
|
||||
CONF_PRESSURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_CELSIUS,
|
||||
UNIT_HECTOPASCAL,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@martgras", "@latonita"]
|
||||
|
||||
bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_base")
|
||||
Oversampling = bmp3xx_ns.enum("Oversampling")
|
||||
OVERSAMPLING_OPTIONS = {
|
||||
"NONE": Oversampling.OVERSAMPLING_NONE,
|
||||
"2X": Oversampling.OVERSAMPLING_X2,
|
||||
"4X": Oversampling.OVERSAMPLING_X4,
|
||||
"8X": Oversampling.OVERSAMPLING_X8,
|
||||
"16X": Oversampling.OVERSAMPLING_X16,
|
||||
"32X": Oversampling.OVERSAMPLING_X32,
|
||||
}
|
||||
|
||||
IIRFilter = bmp3xx_ns.enum("IIRFilter")
|
||||
IIR_FILTER_OPTIONS = {
|
||||
"OFF": IIRFilter.IIR_FILTER_OFF,
|
||||
"2X": IIRFilter.IIR_FILTER_2,
|
||||
"4X": IIRFilter.IIR_FILTER_4,
|
||||
"8X": IIRFilter.IIR_FILTER_8,
|
||||
"16X": IIRFilter.IIR_FILTER_16,
|
||||
"32X": IIRFilter.IIR_FILTER_32,
|
||||
"64X": IIRFilter.IIR_FILTER_64,
|
||||
"128X": IIRFilter.IIR_FILTER_128,
|
||||
}
|
||||
|
||||
|
||||
CONFIG_SCHEMA_BASE = cv.Schema(
|
||||
{
|
||||
cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_CELSIUS,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="2X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_PRESSURE): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_HECTOPASCAL,
|
||||
accuracy_decimals=1,
|
||||
device_class=DEVICE_CLASS_PRESSURE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
).extend(
|
||||
{
|
||||
cv.Optional(CONF_OVERSAMPLING, default="16X"): cv.enum(
|
||||
OVERSAMPLING_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_IIR_FILTER, default="OFF"): cv.enum(
|
||||
IIR_FILTER_OPTIONS, upper=True
|
||||
),
|
||||
}
|
||||
).extend(cv.polling_component_schema("60s"))
|
||||
|
||||
|
||||
async def to_code_base(config):
|
||||
var = cg.new_Pvariable(config[CONF_ID])
|
||||
await cg.register_component(var, config)
|
||||
|
||||
cg.add(var.set_iir_filter_config(config[CONF_IIR_FILTER]))
|
||||
if temperature_config := config.get(CONF_TEMPERATURE):
|
||||
sens = await sensor.new_sensor(temperature_config)
|
||||
cg.add(var.set_temperature_sensor(sens))
|
||||
cg.add(
|
||||
var.set_temperature_oversampling_config(
|
||||
temperature_config[CONF_OVERSAMPLING]
|
||||
)
|
||||
)
|
||||
|
||||
if pressure_config := config.get(CONF_PRESSURE):
|
||||
sens = await sensor.new_sensor(pressure_config)
|
||||
cg.add(var.set_pressure_sensor(sens))
|
||||
cg.add(var.set_pressure_oversampling_config(pressure_config[CONF_OVERSAMPLING]))
|
||||
|
||||
return var
|
||||
@@ -1,29 +0,0 @@
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "bmp3xx_i2c.h"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_i2c {
|
||||
|
||||
static const char *const TAG = "bmp3xx_i2c.sensor";
|
||||
|
||||
bool BMP3XXI2CComponent::read_byte(uint8_t a_register, uint8_t *data) {
|
||||
return I2CDevice::read_byte(a_register, data);
|
||||
};
|
||||
bool BMP3XXI2CComponent::write_byte(uint8_t a_register, uint8_t data) {
|
||||
return I2CDevice::write_byte(a_register, data);
|
||||
};
|
||||
bool BMP3XXI2CComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) {
|
||||
return I2CDevice::read_bytes(a_register, data, len);
|
||||
};
|
||||
bool BMP3XXI2CComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) {
|
||||
return I2CDevice::write_bytes(a_register, data, len);
|
||||
};
|
||||
|
||||
void BMP3XXI2CComponent::dump_config() {
|
||||
LOG_I2C_DEVICE(this);
|
||||
BMP3XXComponent::dump_config();
|
||||
}
|
||||
|
||||
} // namespace bmp3xx_i2c
|
||||
} // namespace esphome
|
||||
@@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
#include "esphome/components/bmp3xx_base/bmp3xx_base.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_i2c {
|
||||
|
||||
class BMP3XXI2CComponent : public bmp3xx_base::BMP3XXComponent, public i2c::I2CDevice {
|
||||
bool read_byte(uint8_t a_register, uint8_t *data) override;
|
||||
bool write_byte(uint8_t a_register, uint8_t data) override;
|
||||
bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override;
|
||||
bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override;
|
||||
void dump_config() override;
|
||||
};
|
||||
|
||||
} // namespace bmp3xx_i2c
|
||||
} // namespace esphome
|
||||
@@ -1,22 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import i2c
|
||||
from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE
|
||||
|
||||
AUTO_LOAD = ["bmp3xx_base"]
|
||||
CODEOWNERS = ["@latonita"]
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_i2c")
|
||||
|
||||
BMP3XXI2CComponent = bmp3xx_ns.class_(
|
||||
"BMP3XXI2CComponent", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(
|
||||
i2c.i2c_device_schema(default_address=0x77)
|
||||
).extend({cv.GenerateID(): cv.declare_id(BMP3XXI2CComponent)})
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await to_code_base(config)
|
||||
await i2c.register_i2c_device(var, config)
|
||||
@@ -1,57 +0,0 @@
|
||||
#include "bmp3xx_spi.h"
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_spi {
|
||||
|
||||
static const char *const TAG = "bmp3xx_spi.sensor";
|
||||
|
||||
uint8_t set_bit(uint8_t num, int position) {
|
||||
int mask = 1 << position;
|
||||
return num | mask;
|
||||
}
|
||||
|
||||
uint8_t clear_bit(uint8_t num, int position) {
|
||||
int mask = 1 << position;
|
||||
return num & ~mask;
|
||||
}
|
||||
|
||||
void BMP3XXSPIComponent::setup() {
|
||||
this->spi_setup();
|
||||
BMP3XXComponent::setup();
|
||||
}
|
||||
|
||||
bool BMP3XXSPIComponent::read_byte(uint8_t a_register, uint8_t *data) {
|
||||
this->enable();
|
||||
this->transfer_byte(set_bit(a_register, 7));
|
||||
*data = this->transfer_byte(0);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMP3XXSPIComponent::write_byte(uint8_t a_register, uint8_t data) {
|
||||
this->enable();
|
||||
this->transfer_byte(clear_bit(a_register, 7));
|
||||
this->transfer_byte(data);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMP3XXSPIComponent::read_bytes(uint8_t a_register, uint8_t *data, size_t len) {
|
||||
this->enable();
|
||||
this->transfer_byte(set_bit(a_register, 7));
|
||||
this->read_array(data, len);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BMP3XXSPIComponent::write_bytes(uint8_t a_register, uint8_t *data, size_t len) {
|
||||
this->enable();
|
||||
this->transfer_byte(clear_bit(a_register, 7));
|
||||
this->transfer_array(data, len);
|
||||
this->disable();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace bmp3xx_spi
|
||||
} // namespace esphome
|
||||
@@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
#include "esphome/components/bmp3xx_base/bmp3xx_base.h"
|
||||
#include "esphome/components/spi/spi.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace bmp3xx_spi {
|
||||
|
||||
class BMP3XXSPIComponent : public bmp3xx_base::BMP3XXComponent,
|
||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
|
||||
spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_1MHZ> {
|
||||
void setup() override;
|
||||
bool read_byte(uint8_t a_register, uint8_t *data) override;
|
||||
bool write_byte(uint8_t a_register, uint8_t data) override;
|
||||
bool read_bytes(uint8_t a_register, uint8_t *data, size_t len) override;
|
||||
bool write_bytes(uint8_t a_register, uint8_t *data, size_t len) override;
|
||||
};
|
||||
|
||||
} // namespace bmp3xx_spi
|
||||
} // namespace esphome
|
||||
@@ -1,22 +0,0 @@
|
||||
import esphome.codegen as cg
|
||||
from esphome.components import spi
|
||||
from ..bmp3xx_base import to_code_base, cv, CONFIG_SCHEMA_BASE
|
||||
|
||||
AUTO_LOAD = ["bmp3xx_base"]
|
||||
CODEOWNERS = ["@latonita"]
|
||||
DEPENDENCIES = ["spi"]
|
||||
|
||||
bmp3xx_ns = cg.esphome_ns.namespace("bmp3xx_spi")
|
||||
|
||||
BMP3XXSPIComponent = bmp3xx_ns.class_(
|
||||
"BMP3XXSPIComponent", cg.PollingComponent, spi.SPIDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = CONFIG_SCHEMA_BASE.extend(spi.spi_device_schema()).extend(
|
||||
{cv.GenerateID(): cv.declare_id(BMP3XXSPIComponent)}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
var = await to_code_base(config)
|
||||
await spi.register_spi_device(var, config)
|
||||
@@ -14,41 +14,15 @@ CONF_HEX = "hex"
|
||||
|
||||
|
||||
def hex_color(value):
|
||||
if isinstance(value, int):
|
||||
value = str(value)
|
||||
if not isinstance(value, str):
|
||||
raise cv.Invalid("Invalid value for hex color")
|
||||
if len(value) != 6:
|
||||
raise cv.Invalid("Hex color must have six digits")
|
||||
raise cv.Invalid("Color must have six digits")
|
||||
try:
|
||||
return int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16)
|
||||
return (int(value[0:2], 16), int(value[2:4], 16), int(value[4:6], 16))
|
||||
except ValueError as exc:
|
||||
raise cv.Invalid("Color must be hexadecimal") from exc
|
||||
|
||||
|
||||
components = {
|
||||
CONF_RED,
|
||||
CONF_RED_INT,
|
||||
CONF_GREEN,
|
||||
CONF_GREEN_INT,
|
||||
CONF_BLUE,
|
||||
CONF_BLUE_INT,
|
||||
CONF_WHITE,
|
||||
CONF_WHITE_INT,
|
||||
}
|
||||
|
||||
|
||||
def validate_color(config):
|
||||
has_components = set(config) & components
|
||||
has_hex = CONF_HEX in config
|
||||
if has_hex and has_components:
|
||||
raise cv.Invalid("Hex color value may not be combined with component values")
|
||||
if not has_hex and not has_components:
|
||||
raise cv.Invalid("Must provide at least one color option")
|
||||
return config
|
||||
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
CONFIG_SCHEMA = cv.Any(
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
|
||||
@@ -60,10 +34,14 @@ CONFIG_SCHEMA = cv.All(
|
||||
cv.Exclusive(CONF_BLUE_INT, "blue"): cv.uint8_t,
|
||||
cv.Exclusive(CONF_WHITE, "white"): cv.percentage,
|
||||
cv.Exclusive(CONF_WHITE_INT, "white"): cv.uint8_t,
|
||||
cv.Optional(CONF_HEX): hex_color,
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
validate_color,
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(ColorStruct),
|
||||
cv.Required(CONF_HEX): hex_color,
|
||||
}
|
||||
).extend(cv.COMPONENT_SCHEMA),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_POWER,
|
||||
CONF_VOLTAGE,
|
||||
CONF_VOLTAGE_GAIN,
|
||||
UNIT_VOLT,
|
||||
UNIT_AMPERE,
|
||||
UNIT_WATT,
|
||||
@@ -34,6 +33,7 @@ CONF_SAMPLES = "samples"
|
||||
CONF_PHASE_OFFSET = "phase_offset"
|
||||
CONF_PGA_GAIN = "pga_gain"
|
||||
CONF_CURRENT_GAIN = "current_gain"
|
||||
CONF_VOLTAGE_GAIN = "voltage_gain"
|
||||
CONF_CURRENT_HPF = "current_hpf"
|
||||
CONF_VOLTAGE_HPF = "voltage_hpf"
|
||||
CONF_PULSE_ENERGY = "pulse_energy"
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate_ir
|
||||
from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ["climate_ir"]
|
||||
|
||||
daikin_brc_ns = cg.esphome_ns.namespace("daikin_brc")
|
||||
DaikinBrcClimate = daikin_brc_ns.class_("DaikinBrcClimate", climate_ir.ClimateIR)
|
||||
|
||||
CONF_USE_FAHRENHEIT = "use_fahrenheit"
|
||||
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
|
||||
{
|
||||
|
||||
@@ -169,7 +169,7 @@ async def to_code(config):
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(DateEntity),
|
||||
cv.Required(CONF_DATE): cv.Any(
|
||||
cv.returning_lambda, cv.date_time(date=True, time=False)
|
||||
cv.returning_lambda, cv.date_time(allowed_time=False)
|
||||
),
|
||||
}
|
||||
),
|
||||
@@ -200,7 +200,7 @@ async def datetime_date_set_to_code(config, action_id, template_arg, args):
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(TimeEntity),
|
||||
cv.Required(CONF_TIME): cv.Any(
|
||||
cv.returning_lambda, cv.date_time(date=False, time=True)
|
||||
cv.returning_lambda, cv.date_time(allowed_date=False)
|
||||
),
|
||||
}
|
||||
),
|
||||
@@ -230,9 +230,7 @@ async def datetime_time_set_to_code(config, action_id, template_arg, args):
|
||||
cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.use_id(DateTimeEntity),
|
||||
cv.Required(CONF_DATETIME): cv.Any(
|
||||
cv.returning_lambda, cv.date_time(date=True, time=True)
|
||||
),
|
||||
cv.Required(CONF_DATETIME): cv.Any(cv.returning_lambda, cv.date_time()),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2,7 +2,7 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.automation import maybe_simple_id
|
||||
from esphome.const import CONF_FACTORY_RESET, CONF_ID, CONF_SENSITIVITY
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.components import uart
|
||||
|
||||
CODEOWNERS = ["@niklasweber"]
|
||||
@@ -28,6 +28,8 @@ CONF_DELAY_AFTER_DETECT = "delay_after_detect"
|
||||
CONF_DELAY_AFTER_DISAPPEAR = "delay_after_disappear"
|
||||
CONF_DETECTION_SEGMENTS = "detection_segments"
|
||||
CONF_OUTPUT_LATENCY = "output_latency"
|
||||
CONF_FACTORY_RESET = "factory_reset"
|
||||
CONF_SENSITIVITY = "sensitivity"
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.Schema(
|
||||
|
||||
@@ -15,11 +15,11 @@ class Rect {
|
||||
int16_t h; ///< Height of region
|
||||
|
||||
Rect() : x(VALUE_NO_SET), y(VALUE_NO_SET), w(VALUE_NO_SET), h(VALUE_NO_SET) {} // NOLINT
|
||||
inline Rect(int16_t x, int16_t y, int16_t w, int16_t h) ESPHOME_ALWAYS_INLINE : x(x), y(y), w(w), h(h) {}
|
||||
inline Rect(int16_t x, int16_t y, int16_t w, int16_t h) ALWAYS_INLINE : x(x), y(y), w(w), h(h) {}
|
||||
inline int16_t x2() const { return this->x + this->w; }; ///< X coordinate of corner
|
||||
inline int16_t y2() const { return this->y + this->h; }; ///< Y coordinate of corner
|
||||
|
||||
inline bool is_set() const ESPHOME_ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); }
|
||||
inline bool is_set() const ALWAYS_INLINE { return (this->h != VALUE_NO_SET) && (this->w != VALUE_NO_SET); }
|
||||
|
||||
void expand(int16_t horizontal, int16_t vertical);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ CODEOWNERS = ["@numo68"]
|
||||
|
||||
display_menu_base_ns = cg.esphome_ns.namespace("display_menu_base")
|
||||
|
||||
CONF_DISPLAY_ID = "display_id"
|
||||
|
||||
CONF_ROTARY = "rotary"
|
||||
CONF_JOYSTICK = "joystick"
|
||||
|
||||
@@ -4,7 +4,6 @@ from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
CONF_EXTERNAL_TEMPERATURE,
|
||||
CONF_ID,
|
||||
CONF_INTERNAL_TEMPERATURE,
|
||||
CONF_SPEED,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
@@ -17,6 +16,7 @@ from .. import EMC2101_COMPONENT_SCHEMA, CONF_EMC2101_ID, emc2101_ns
|
||||
|
||||
DEPENDENCIES = ["emc2101"]
|
||||
|
||||
CONF_INTERNAL_TEMPERATURE = "internal_temperature"
|
||||
CONF_DUTY_CYCLE = "duty_cycle"
|
||||
|
||||
EMC2101Sensor = emc2101_ns.class_("EMC2101Sensor", cg.PollingComponent)
|
||||
|
||||
@@ -2,7 +2,6 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
CONF_COMPENSATION,
|
||||
CONF_ECO2,
|
||||
CONF_HUMIDITY,
|
||||
CONF_ID,
|
||||
@@ -28,6 +27,7 @@ ENS160Component = ens160_ns.class_(
|
||||
)
|
||||
|
||||
CONF_AQI = "aqi"
|
||||
CONF_COMPENSATION = "compensation"
|
||||
UNIT_INDEX = "index"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
|
||||
@@ -227,7 +227,7 @@ ARDUINO_PLATFORM_VERSION = cv.Version(5, 4, 0)
|
||||
# The default/recommended esp-idf framework version
|
||||
# - https://github.com/espressif/esp-idf/releases
|
||||
# - https://api.registry.platformio.org/v3/packages/platformio/tool/framework-espidf
|
||||
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 7)
|
||||
RECOMMENDED_ESP_IDF_FRAMEWORK_VERSION = cv.Version(4, 4, 6)
|
||||
# The platformio/espressif32 version to use for esp-idf frameworks
|
||||
# - https://github.com/platformio/platform-espressif32/releases
|
||||
# - https://api.registry.platformio.org/v3/packages/platformio/platform/espressif32
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.const import CONF_ENABLE_ON_BOOT, CONF_ID
|
||||
from esphome.const import CONF_ID
|
||||
from esphome.core import CORE
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant, const
|
||||
|
||||
@@ -11,6 +11,7 @@ CONFLICTS_WITH = ["esp32_ble_beacon"]
|
||||
|
||||
CONF_BLE_ID = "ble_id"
|
||||
CONF_IO_CAPABILITY = "io_capability"
|
||||
CONF_ENABLE_ON_BOOT = "enable_on_boot"
|
||||
|
||||
NO_BLUETOOTH_VARIANTS = [const.VARIANT_ESP32S2]
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ from esphome.const import (
|
||||
CONF_BRIGHTNESS,
|
||||
CONF_CONTRAST,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_VSYNC_PIN,
|
||||
)
|
||||
from esphome.core import CORE
|
||||
from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
@@ -113,6 +112,7 @@ ENUM_SPECIAL_EFFECT = {
|
||||
}
|
||||
|
||||
# pin assignment
|
||||
CONF_VSYNC_PIN = "vsync_pin"
|
||||
CONF_HREF_PIN = "href_pin"
|
||||
CONF_PIXEL_CLOCK_PIN = "pixel_clock_pin"
|
||||
CONF_EXTERNAL_CLOCK = "external_clock"
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include "ethernet_component.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include <lwip/dns.h>
|
||||
#include <cinttypes>
|
||||
#include <lwip/dns.h>
|
||||
#include "esp_event.h"
|
||||
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
@@ -184,10 +184,6 @@ void EthernetComponent::setup() {
|
||||
// KSZ8081RNA default is incorrect. It expects a 25MHz clock instead of the 50MHz we provide.
|
||||
this->ksz8081_set_clock_reference_(mac);
|
||||
}
|
||||
if (this->type_ == ETHERNET_TYPE_RTL8201 && this->clk_mode_ == EMAC_CLK_EXT_IN) {
|
||||
// Change in default behavior of RTL8201FI may require register setting to enable external clock
|
||||
this->rtl8201_set_rmii_mode_(mac);
|
||||
}
|
||||
#endif
|
||||
|
||||
// use ESP internal eth mac
|
||||
@@ -558,10 +554,9 @@ bool EthernetComponent::powerdown() {
|
||||
}
|
||||
|
||||
#ifndef USE_ETHERNET_SPI
|
||||
|
||||
constexpr uint8_t KSZ80XX_PC2R_REG_ADDR = 0x1F;
|
||||
|
||||
void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) {
|
||||
#define KSZ80XX_PC2R_REG_ADDR (0x1F)
|
||||
|
||||
esp_err_t err;
|
||||
|
||||
uint32_t phy_control_2;
|
||||
@@ -586,47 +581,9 @@ void EthernetComponent::ksz8081_set_clock_reference_(esp_eth_mac_t *mac) {
|
||||
ESPHL_ERROR_CHECK(err, "Read PHY Control 2 failed");
|
||||
ESP_LOGVV(TAG, "KSZ8081 PHY Control 2: %s", format_hex_pretty((u_int8_t *) &phy_control_2, 2).c_str());
|
||||
}
|
||||
|
||||
#undef KSZ80XX_PC2R_REG_ADDR
|
||||
}
|
||||
constexpr uint8_t RTL8201_RMSR_REG_ADDR = 0x10;
|
||||
void EthernetComponent::rtl8201_set_rmii_mode_(esp_eth_mac_t *mac) {
|
||||
esp_err_t err;
|
||||
uint32_t phy_rmii_mode;
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x07);
|
||||
ESPHL_ERROR_CHECK(err, "Setting Page 7 failed");
|
||||
|
||||
/*
|
||||
* RTL8201 RMII Mode Setting Register (RMSR)
|
||||
* Page 7 Register 16
|
||||
*
|
||||
* bit 0 Reserved 0
|
||||
* bit 1 Rg_rmii_rxdsel 1 (default)
|
||||
* bit 2 Rg_rmii_rxdv_sel: 0 (default)
|
||||
* bit 3 RMII Mode: 1 (RMII Mode)
|
||||
* bit 4~7 Rg_rmii_rx_offset: 1111 (default)
|
||||
* bit 8~11 Rg_rmii_tx_offset: 1111 (default)
|
||||
* bit 12 Rg_rmii_clkdir: 1 (Input)
|
||||
* bit 13~15 Reserved 000
|
||||
*
|
||||
* Binary: 0001 1111 1111 1010
|
||||
* Hex: 0x1FFA
|
||||
*
|
||||
*/
|
||||
|
||||
err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode));
|
||||
ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed");
|
||||
ESP_LOGV(TAG, "Hardware default RTL8201 RMII Mode Register is: 0x%04X", phy_rmii_mode);
|
||||
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, 0x1FFA);
|
||||
ESPHL_ERROR_CHECK(err, "Setting Register 16 RMII Mode Setting failed");
|
||||
|
||||
err = mac->read_phy_reg(mac, this->phy_addr_, RTL8201_RMSR_REG_ADDR, &(phy_rmii_mode));
|
||||
ESPHL_ERROR_CHECK(err, "Read PHY RMSR Register failed");
|
||||
ESP_LOGV(TAG, "Setting RTL8201 RMII Mode Register to: 0x%04X", phy_rmii_mode);
|
||||
|
||||
err = mac->write_phy_reg(mac, this->phy_addr_, 0x1f, 0x0);
|
||||
ESPHL_ERROR_CHECK(err, "Setting Page 0 failed");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace ethernet
|
||||
|
||||
@@ -86,8 +86,6 @@ class EthernetComponent : public Component {
|
||||
void dump_connect_params_();
|
||||
/// @brief Set `RMII Reference Clock Select` bit for KSZ8081.
|
||||
void ksz8081_set_clock_reference_(esp_eth_mac_t *mac);
|
||||
/// @brief Set `RMII Mode Setting Register` for RTL8201.
|
||||
void rtl8201_set_rmii_mode_(esp_eth_mac_t *mac);
|
||||
|
||||
std::string use_address_;
|
||||
#ifdef USE_ETHERNET_SPI
|
||||
|
||||
@@ -49,16 +49,7 @@ def _process_git_config(config: dict, refresh) -> str:
|
||||
password=config.get(CONF_PASSWORD),
|
||||
)
|
||||
|
||||
if path := config.get(CONF_PATH):
|
||||
if (repo_dir / path).is_dir():
|
||||
components_dir = repo_dir / path
|
||||
else:
|
||||
raise cv.Invalid(
|
||||
"Could not find components folder for source. Please check the source contains a '"
|
||||
+ path
|
||||
+ "' folder"
|
||||
)
|
||||
elif (repo_dir / "esphome" / "components").is_dir():
|
||||
if (repo_dir / "esphome" / "components").is_dir():
|
||||
components_dir = repo_dir / "esphome" / "components"
|
||||
elif (repo_dir / "components").is_dir():
|
||||
components_dir = repo_dir / "components"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import display, font, color
|
||||
from esphome.const import CONF_DISPLAY, CONF_ID, CONF_TRIGGER_ID
|
||||
from esphome.const import CONF_ID, CONF_TRIGGER_ID
|
||||
from esphome import automation, core
|
||||
|
||||
from esphome.components.display_menu_base import (
|
||||
@@ -10,6 +10,7 @@ from esphome.components.display_menu_base import (
|
||||
display_menu_to_code,
|
||||
)
|
||||
|
||||
CONF_DISPLAY = "display"
|
||||
CONF_FONT = "font"
|
||||
CONF_MENU_ITEM_VALUE = "menu_item_value"
|
||||
CONF_FOREGROUND_COLOR = "foreground_color"
|
||||
|
||||
@@ -6,14 +6,12 @@ from esphome.components import uart, climate, logger
|
||||
from esphome import automation
|
||||
from esphome.const import (
|
||||
CONF_BEEPER,
|
||||
CONF_DISPLAY,
|
||||
CONF_ID,
|
||||
CONF_LEVEL,
|
||||
CONF_LOGGER,
|
||||
CONF_LOGS,
|
||||
CONF_MAX_TEMPERATURE,
|
||||
CONF_MIN_TEMPERATURE,
|
||||
CONF_OUTDOOR_TEMPERATURE,
|
||||
CONF_PROTOCOL,
|
||||
CONF_SUPPORTED_MODES,
|
||||
CONF_SUPPORTED_PRESETS,
|
||||
@@ -45,9 +43,11 @@ CONF_ALTERNATIVE_SWING_CONTROL = "alternative_swing_control"
|
||||
CONF_ANSWER_TIMEOUT = "answer_timeout"
|
||||
CONF_CONTROL_METHOD = "control_method"
|
||||
CONF_CONTROL_PACKET_SIZE = "control_packet_size"
|
||||
CONF_DISPLAY = "display"
|
||||
CONF_HORIZONTAL_AIRFLOW = "horizontal_airflow"
|
||||
CONF_ON_ALARM_START = "on_alarm_start"
|
||||
CONF_ON_ALARM_END = "on_alarm_end"
|
||||
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
||||
CONF_VERTICAL_AIRFLOW = "vertical_airflow"
|
||||
CONF_WIFI_SIGNAL = "wifi_signal"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
CONF_OUTDOOR_TEMPERATURE,
|
||||
CONF_POWER,
|
||||
CONF_HUMIDITY,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
@@ -42,6 +41,7 @@ CONF_OUTDOOR_COIL_TEMPERATURE = "outdoor_coil_temperature"
|
||||
CONF_OUTDOOR_DEFROST_TEMPERATURE = "outdoor_defrost_temperature"
|
||||
CONF_OUTDOOR_IN_AIR_TEMPERATURE = "outdoor_in_air_temperature"
|
||||
CONF_OUTDOOR_OUT_AIR_TEMPERATURE = "outdoor_out_air_temperature"
|
||||
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
||||
|
||||
# Additional icons
|
||||
ICON_SNOWFLAKE_THERMOMETER = "mdi:snowflake-thermometer"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "hmc5883l.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/application.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace hmc5883l {
|
||||
@@ -32,10 +31,6 @@ void HMC5883LComponent::setup() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->get_update_interval() < App.get_loop_interval()) {
|
||||
high_freq_.start();
|
||||
}
|
||||
|
||||
if (id[0] != 0x48 || id[1] != 0x34 || id[2] != 0x33) {
|
||||
this->error_code_ = ID_REGISTERS;
|
||||
this->mark_failed();
|
||||
|
||||
@@ -63,7 +63,6 @@ class HMC5883LComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
COMMUNICATION_FAILED,
|
||||
ID_REGISTERS,
|
||||
} error_code_;
|
||||
HighFrequencyLoopRequester high_freq_;
|
||||
};
|
||||
|
||||
} // namespace hmc5883l
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_FIELD_STRENGTH_X,
|
||||
CONF_FIELD_STRENGTH_Y,
|
||||
CONF_FIELD_STRENGTH_Z,
|
||||
CONF_HEADING,
|
||||
CONF_ID,
|
||||
CONF_OVERSAMPLING,
|
||||
CONF_RANGE,
|
||||
@@ -22,6 +21,7 @@ DEPENDENCIES = ["i2c"]
|
||||
|
||||
hmc5883l_ns = cg.esphome_ns.namespace("hmc5883l")
|
||||
|
||||
CONF_HEADING = "heading"
|
||||
|
||||
HMC5883LComponent = hmc5883l_ns.class_(
|
||||
"HMC5883LComponent", cg.PollingComponent, i2c.I2CDevice
|
||||
|
||||
@@ -7,7 +7,6 @@ from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_LAMBDA,
|
||||
CONF_MODEL,
|
||||
CONF_OE_PIN,
|
||||
CONF_PAGES,
|
||||
CONF_WAKEUP_PIN,
|
||||
)
|
||||
@@ -30,6 +29,7 @@ CONF_GREYSCALE = "greyscale"
|
||||
CONF_GMOD_PIN = "gmod_pin"
|
||||
CONF_GPIO0_ENABLE_PIN = "gpio0_enable_pin"
|
||||
CONF_LE_PIN = "le_pin"
|
||||
CONF_OE_PIN = "oe_pin"
|
||||
CONF_PARTIAL_UPDATING = "partial_updating"
|
||||
CONF_POWERUP_PIN = "powerup_pin"
|
||||
CONF_SPH_PIN = "sph_pin"
|
||||
|
||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
|
||||
from esphome.components import i2c, sensor
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_INTERNAL_TEMPERATURE,
|
||||
CONF_TEMPERATURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
@@ -11,6 +10,7 @@ from esphome.const import (
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
)
|
||||
|
||||
CONF_INTERNAL_TEMPERATURE = "internal_temperature"
|
||||
DEPENDENCIES = ["i2c"]
|
||||
|
||||
kmeteriso_ns = cg.esphome_ns.namespace("kmeteriso")
|
||||
|
||||
@@ -3,7 +3,6 @@ import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_DIMENSIONS,
|
||||
CONF_DISPLAY_ID,
|
||||
)
|
||||
from esphome.core.entity_helpers import inherit_property_from
|
||||
from esphome.components import lcd_base
|
||||
@@ -19,6 +18,8 @@ AUTO_LOAD = ["display_menu_base"]
|
||||
|
||||
lcd_menu_ns = cg.esphome_ns.namespace("lcd_menu")
|
||||
|
||||
CONF_DISPLAY_ID = "display_id"
|
||||
|
||||
CONF_MARK_SELECTED = "mark_selected"
|
||||
CONF_MARK_EDITING = "mark_editing"
|
||||
CONF_MARK_SUBMENU = "mark_submenu"
|
||||
|
||||
@@ -8,13 +8,13 @@ from esphome.const import (
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
ICON_MOTION_SENSOR,
|
||||
ICON_ACCOUNT,
|
||||
CONF_HAS_TARGET,
|
||||
CONF_HAS_MOVING_TARGET,
|
||||
CONF_HAS_STILL_TARGET,
|
||||
)
|
||||
from . import CONF_LD2410_ID, LD2410Component
|
||||
|
||||
DEPENDENCIES = ["ld2410"]
|
||||
CONF_HAS_TARGET = "has_target"
|
||||
CONF_HAS_MOVING_TARGET = "has_moving_target"
|
||||
CONF_HAS_STILL_TARGET = "has_still_target"
|
||||
CONF_OUT_PIN_PRESENCE_STATUS = "out_pin_presence_status"
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
|
||||
@@ -2,8 +2,6 @@ import esphome.codegen as cg
|
||||
from esphome.components import button
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_FACTORY_RESET,
|
||||
CONF_RESTART,
|
||||
DEVICE_CLASS_RESTART,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
@@ -17,6 +15,8 @@ QueryButton = ld2410_ns.class_("QueryButton", button.Button)
|
||||
ResetButton = ld2410_ns.class_("ResetButton", button.Button)
|
||||
RestartButton = ld2410_ns.class_("RestartButton", button.Button)
|
||||
|
||||
CONF_FACTORY_RESET = "factory_reset"
|
||||
CONF_RESTART = "restart"
|
||||
CONF_QUERY_PARAMS = "query_params"
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_ID, DEVICE_CLASS_OCCUPANCY, CONF_HAS_TARGET
|
||||
from esphome.const import CONF_ID, DEVICE_CLASS_OCCUPANCY
|
||||
from .. import ld2420_ns, LD2420Component, CONF_LD2420_ID
|
||||
|
||||
LD2420BinarySensor = ld2420_ns.class_(
|
||||
"LD2420BinarySensor", binary_sensor.BinarySensor, cg.Component
|
||||
)
|
||||
|
||||
CONF_HAS_TARGET = "has_target"
|
||||
|
||||
CONFIG_SCHEMA = cv.All(
|
||||
cv.COMPONENT_SCHEMA.extend(
|
||||
|
||||
@@ -2,7 +2,6 @@ import esphome.codegen as cg
|
||||
from esphome.components import button
|
||||
import esphome.config_validation as cv
|
||||
from esphome.const import (
|
||||
CONF_FACTORY_RESET,
|
||||
DEVICE_CLASS_RESTART,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
ENTITY_CATEGORY_CONFIG,
|
||||
@@ -20,6 +19,7 @@ LD2420FactoryResetButton = ld2420_ns.class_("LD2420FactoryResetButton", button.B
|
||||
CONF_APPLY_CONFIG = "apply_config"
|
||||
CONF_REVERT_CONFIG = "revert_config"
|
||||
CONF_RESTART_MODULE = "restart_module"
|
||||
CONF_FACTORY_RESET = "factory_reset"
|
||||
|
||||
|
||||
CONFIG_SCHEMA = {
|
||||
|
||||
@@ -11,54 +11,54 @@ class ESPColorCorrection {
|
||||
void set_max_brightness(const Color &max_brightness) { this->max_brightness_ = max_brightness; }
|
||||
void set_local_brightness(uint8_t local_brightness) { this->local_brightness_ = local_brightness; }
|
||||
void calculate_gamma_table(float gamma);
|
||||
inline Color color_correct(Color color) const ESPHOME_ALWAYS_INLINE {
|
||||
inline Color color_correct(Color color) const ALWAYS_INLINE {
|
||||
// corrected = (uncorrected * max_brightness * local_brightness) ^ gamma
|
||||
return Color(this->color_correct_red(color.red), this->color_correct_green(color.green),
|
||||
this->color_correct_blue(color.blue), this->color_correct_white(color.white));
|
||||
}
|
||||
inline uint8_t color_correct_red(uint8_t red) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_correct_red(uint8_t red) const ALWAYS_INLINE {
|
||||
uint8_t res = esp_scale8(esp_scale8(red, this->max_brightness_.red), this->local_brightness_);
|
||||
return this->gamma_table_[res];
|
||||
}
|
||||
inline uint8_t color_correct_green(uint8_t green) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_correct_green(uint8_t green) const ALWAYS_INLINE {
|
||||
uint8_t res = esp_scale8(esp_scale8(green, this->max_brightness_.green), this->local_brightness_);
|
||||
return this->gamma_table_[res];
|
||||
}
|
||||
inline uint8_t color_correct_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_correct_blue(uint8_t blue) const ALWAYS_INLINE {
|
||||
uint8_t res = esp_scale8(esp_scale8(blue, this->max_brightness_.blue), this->local_brightness_);
|
||||
return this->gamma_table_[res];
|
||||
}
|
||||
inline uint8_t color_correct_white(uint8_t white) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_correct_white(uint8_t white) const ALWAYS_INLINE {
|
||||
uint8_t res = esp_scale8(esp_scale8(white, this->max_brightness_.white), this->local_brightness_);
|
||||
return this->gamma_table_[res];
|
||||
}
|
||||
inline Color color_uncorrect(Color color) const ESPHOME_ALWAYS_INLINE {
|
||||
inline Color color_uncorrect(Color color) const ALWAYS_INLINE {
|
||||
// uncorrected = corrected^(1/gamma) / (max_brightness * local_brightness)
|
||||
return Color(this->color_uncorrect_red(color.red), this->color_uncorrect_green(color.green),
|
||||
this->color_uncorrect_blue(color.blue), this->color_uncorrect_white(color.white));
|
||||
}
|
||||
inline uint8_t color_uncorrect_red(uint8_t red) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_uncorrect_red(uint8_t red) const ALWAYS_INLINE {
|
||||
if (this->max_brightness_.red == 0 || this->local_brightness_ == 0)
|
||||
return 0;
|
||||
uint16_t uncorrected = this->gamma_reverse_table_[red] * 255UL;
|
||||
uint8_t res = ((uncorrected / this->max_brightness_.red) * 255UL) / this->local_brightness_;
|
||||
return res;
|
||||
}
|
||||
inline uint8_t color_uncorrect_green(uint8_t green) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_uncorrect_green(uint8_t green) const ALWAYS_INLINE {
|
||||
if (this->max_brightness_.green == 0 || this->local_brightness_ == 0)
|
||||
return 0;
|
||||
uint16_t uncorrected = this->gamma_reverse_table_[green] * 255UL;
|
||||
uint8_t res = ((uncorrected / this->max_brightness_.green) * 255UL) / this->local_brightness_;
|
||||
return res;
|
||||
}
|
||||
inline uint8_t color_uncorrect_blue(uint8_t blue) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_uncorrect_blue(uint8_t blue) const ALWAYS_INLINE {
|
||||
if (this->max_brightness_.blue == 0 || this->local_brightness_ == 0)
|
||||
return 0;
|
||||
uint16_t uncorrected = this->gamma_reverse_table_[blue] * 255UL;
|
||||
uint8_t res = ((uncorrected / this->max_brightness_.blue) * 255UL) / this->local_brightness_;
|
||||
return res;
|
||||
}
|
||||
inline uint8_t color_uncorrect_white(uint8_t white) const ESPHOME_ALWAYS_INLINE {
|
||||
inline uint8_t color_uncorrect_white(uint8_t white) const ALWAYS_INLINE {
|
||||
if (this->max_brightness_.white == 0 || this->local_brightness_ == 0)
|
||||
return 0;
|
||||
uint16_t uncorrected = this->gamma_reverse_table_[white] * 255UL;
|
||||
|
||||
@@ -24,11 +24,11 @@ struct ESPHSVColor {
|
||||
};
|
||||
uint8_t raw[3];
|
||||
};
|
||||
inline ESPHSVColor() ESPHOME_ALWAYS_INLINE : h(0), s(0), v(0) { // NOLINT
|
||||
inline ESPHSVColor() ALWAYS_INLINE : h(0), s(0), v(0) { // NOLINT
|
||||
}
|
||||
inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ESPHOME_ALWAYS_INLINE : hue(hue),
|
||||
saturation(saturation),
|
||||
value(value) {}
|
||||
inline ESPHSVColor(uint8_t hue, uint8_t saturation, uint8_t value) ALWAYS_INLINE : hue(hue),
|
||||
saturation(saturation),
|
||||
value(value) {}
|
||||
Color to_rgb() const;
|
||||
};
|
||||
|
||||
|
||||
@@ -39,23 +39,7 @@ void Logger::write_header_(int level, const char *tag, int line) {
|
||||
|
||||
const char *color = LOG_LEVEL_COLORS[level];
|
||||
const char *letter = LOG_LEVEL_LETTERS[level];
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
|
||||
#else
|
||||
void *current_task = nullptr;
|
||||
#endif
|
||||
if (current_task == main_task_) {
|
||||
this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line);
|
||||
} else {
|
||||
const char *thread_name = "";
|
||||
#if defined(USE_ESP32)
|
||||
thread_name = pcTaskGetName(current_task);
|
||||
#elif defined(USE_LIBRETINY)
|
||||
thread_name = pcTaskGetTaskName(current_task);
|
||||
#endif
|
||||
this->printf_to_buffer_("%s[%s][%s:%03u]%s[%s]%s: ", color, letter, tag, line,
|
||||
ESPHOME_LOG_BOLD(ESPHOME_LOG_COLOR_RED), thread_name, color);
|
||||
}
|
||||
this->printf_to_buffer_("%s[%s][%s:%03u]: ", color, letter, tag, line);
|
||||
}
|
||||
|
||||
void HOT Logger::log_vprintf_(int level, const char *tag, int line, const char *format, va_list args) { // NOLINT
|
||||
@@ -143,9 +127,6 @@ void HOT Logger::log_message_(int level, const char *tag, int offset) {
|
||||
Logger::Logger(uint32_t baud_rate, size_t tx_buffer_size) : baud_rate_(baud_rate), tx_buffer_size_(tx_buffer_size) {
|
||||
// add 1 to buffer size for null terminator
|
||||
this->tx_buffer_ = new char[this->tx_buffer_size_ + 1]; // NOLINT
|
||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
||||
this->main_task_ = xTaskGetCurrentTaskHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGER_USB_CDC
|
||||
|
||||
@@ -167,7 +167,6 @@ class Logger : public Component {
|
||||
CallbackManager<void(int, const char *, const char *)> log_callback_{};
|
||||
/// Prevents recursive log calls, if true a log message is already being processed.
|
||||
bool recursion_guard_ = false;
|
||||
void *main_task_ = nullptr;
|
||||
};
|
||||
|
||||
extern Logger *global_logger; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import CONF_ID, CONF_KEY, CONF_ROW, CONF_COL
|
||||
from esphome.const import CONF_ID, CONF_KEY
|
||||
from .. import MatrixKeypad, matrix_keypad_ns, CONF_KEYPAD_ID
|
||||
|
||||
CONF_ROW = "row"
|
||||
CONF_COL = "col"
|
||||
|
||||
DEPENDENCIES = ["matrix_keypad"]
|
||||
|
||||
MatrixKeypadBinarySensor = matrix_keypad_ns.class_(
|
||||
|
||||
@@ -4,7 +4,6 @@ from esphome.components import sensor, voltage_sampler
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_NUMBER,
|
||||
CONF_REFERENCE_VOLTAGE,
|
||||
UNIT_VOLT,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
@@ -23,6 +22,7 @@ MCP3008Sensor = mcp3008_ns.class_(
|
||||
voltage_sampler.VoltageSampler,
|
||||
cg.Parented.template(MCP3008),
|
||||
)
|
||||
CONF_REFERENCE_VOLTAGE = "reference_voltage"
|
||||
CONF_MCP3008_ID = "mcp3008_id"
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import spi
|
||||
from esphome.const import CONF_ID, CONF_REFERENCE_VOLTAGE
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
DEPENDENCIES = ["spi"]
|
||||
MULTI_CONF = True
|
||||
@@ -10,6 +10,7 @@ CODEOWNERS = ["@rsumner"]
|
||||
mcp3204_ns = cg.esphome_ns.namespace("mcp3204")
|
||||
MCP3204 = mcp3204_ns.class_("MCP3204", cg.Component, spi.SPIDevice)
|
||||
|
||||
CONF_REFERENCE_VOLTAGE = "reference_voltage"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
|
||||
@@ -3,13 +3,7 @@ import esphome.config_validation as cv
|
||||
import esphome.codegen as cg
|
||||
|
||||
from esphome.automation import maybe_simple_id
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ON_STATE,
|
||||
CONF_TRIGGER_ID,
|
||||
CONF_VOLUME,
|
||||
CONF_ON_IDLE,
|
||||
)
|
||||
from esphome.const import CONF_ID, CONF_ON_STATE, CONF_TRIGGER_ID, CONF_VOLUME
|
||||
from esphome.core import CORE
|
||||
from esphome.coroutine import coroutine_with_priority
|
||||
from esphome.cpp_helpers import setup_entity
|
||||
@@ -49,6 +43,7 @@ VolumeSetAction = media_player_ns.class_(
|
||||
)
|
||||
|
||||
|
||||
CONF_ON_IDLE = "on_idle"
|
||||
CONF_ON_PLAY = "on_play"
|
||||
CONF_ON_PAUSE = "on_pause"
|
||||
CONF_MEDIA_URL = "media_url"
|
||||
|
||||
@@ -11,7 +11,6 @@ from esphome.const import (
|
||||
CONF_CUSTOM_PRESETS,
|
||||
CONF_ID,
|
||||
CONF_NUM_ATTEMPTS,
|
||||
CONF_OUTDOOR_TEMPERATURE,
|
||||
CONF_PERIOD,
|
||||
CONF_SUPPORTED_MODES,
|
||||
CONF_SUPPORTED_PRESETS,
|
||||
@@ -38,6 +37,7 @@ from esphome.components.climate import (
|
||||
CODEOWNERS = ["@dudanov"]
|
||||
DEPENDENCIES = ["climate", "uart"]
|
||||
AUTO_LOAD = ["sensor"]
|
||||
CONF_OUTDOOR_TEMPERATURE = "outdoor_temperature"
|
||||
CONF_POWER_USAGE = "power_usage"
|
||||
CONF_HUMIDITY_SETPOINT = "humidity_setpoint"
|
||||
midea_ac_ns = cg.esphome_ns.namespace("midea").namespace("ac")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import climate_ir
|
||||
from esphome.const import CONF_ID, CONF_USE_FAHRENHEIT
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
AUTO_LOAD = ["climate_ir", "coolix"]
|
||||
CODEOWNERS = ["@dudanov"]
|
||||
@@ -9,6 +9,7 @@ CODEOWNERS = ["@dudanov"]
|
||||
midea_ir_ns = cg.esphome_ns.namespace("midea_ir")
|
||||
MideaIR = midea_ir_ns.class_("MideaIR", climate_ir.ClimateIR)
|
||||
|
||||
CONF_USE_FAHRENHEIT = "use_fahrenheit"
|
||||
|
||||
CONFIG_SCHEMA = climate_ir.CLIMATE_IR_WITH_RECEIVER_SCHEMA.extend(
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_FIELD_STRENGTH_X,
|
||||
CONF_FIELD_STRENGTH_Y,
|
||||
CONF_FIELD_STRENGTH_Z,
|
||||
CONF_HEADING,
|
||||
CONF_ID,
|
||||
ICON_MAGNET,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
@@ -20,6 +19,8 @@ DEPENDENCIES = ["i2c"]
|
||||
|
||||
mmc5603_ns = cg.esphome_ns.namespace("mmc5603")
|
||||
|
||||
CONF_HEADING = "heading"
|
||||
|
||||
MMC5603Component = mmc5603_ns.class_(
|
||||
"MMC5603Component", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
@@ -54,12 +54,7 @@ from esphome.components.esp32 import add_idf_sdkconfig_option
|
||||
|
||||
DEPENDENCIES = ["network"]
|
||||
|
||||
|
||||
def AUTO_LOAD():
|
||||
if CORE.is_esp8266 or CORE.is_libretiny:
|
||||
return ["async_tcp", "json"]
|
||||
return ["json"]
|
||||
|
||||
AUTO_LOAD = ["json"]
|
||||
|
||||
CONF_IDF_SEND_ASYNC = "idf_send_async"
|
||||
CONF_SKIP_CERT_CN_CHECK = "skip_cert_cn_check"
|
||||
|
||||
@@ -25,7 +25,7 @@ from .base_component import (
|
||||
CONF_EXIT_REPARSE_ON_START,
|
||||
)
|
||||
|
||||
CODEOWNERS = ["@senexcrenshaw", "@edwardtfn"]
|
||||
CODEOWNERS = ["@senexcrenshaw"]
|
||||
|
||||
DEPENDENCIES = ["uart"]
|
||||
AUTO_LOAD = ["binary_sensor", "switch", "sensor", "text_sensor"]
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "esphome/components/display/display_color_utils.h"
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ARDUINO
|
||||
#ifdef ARDUINO
|
||||
#ifdef USE_ESP32
|
||||
#include <HTTPClient.h>
|
||||
#endif // USE_ESP32
|
||||
@@ -22,7 +22,7 @@
|
||||
#endif // USE_ESP8266
|
||||
#elif defined(USE_ESP_IDF)
|
||||
#include <esp_http_client.h>
|
||||
#endif // ARDUINO vs USE_ESP_IDF
|
||||
#endif // ARDUINO vs ESP-IDF
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
|
||||
namespace esphome {
|
||||
@@ -976,7 +976,6 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
* @return Whether the send was successful.
|
||||
*/
|
||||
bool send_command(const char *command);
|
||||
|
||||
/**
|
||||
* Manually send a raw formatted command to the display.
|
||||
* @param format The printf-style command format, like "vis %s,0"
|
||||
@@ -987,33 +986,20 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
/**
|
||||
* Set the tft file URL. https seems problematic with Arduino..
|
||||
* Set the tft file URL. https seems problematic with arduino..
|
||||
*/
|
||||
void set_tft_url(const std::string &tft_url) { this->tft_url_ = tft_url; }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Uploads the TFT file to the Nextion display.
|
||||
*
|
||||
* This function initiates the upload of a TFT file to the Nextion display. Users can specify a target baud rate for
|
||||
* the transfer. If the provided baud rate is not supported by Nextion, the function defaults to using the current
|
||||
* baud rate set for the display. If no baud rate is specified (or if 0 is passed), the current baud rate is used.
|
||||
*
|
||||
* Supported baud rates are: 2400, 4800, 9600, 19200, 31250, 38400, 57600, 115200, 230400, 250000, 256000, 512000
|
||||
* and 921600. Selecting a baud rate supported by both the Nextion display and the host hardware is essential for
|
||||
* ensuring a successful upload process.
|
||||
*
|
||||
* @param baud_rate The desired baud rate for the TFT file transfer, specified as an unsigned 32-bit integer.
|
||||
* If the specified baud rate is not supported, or if 0 is passed, the function will use the current baud rate.
|
||||
* The default value is 0, which implies using the current baud rate.
|
||||
* Upload the tft file and soft reset Nextion
|
||||
* @param exit_reparse If true, the function exits reparse mode before uploading the TFT file. This parameter
|
||||
* defaults to true, ensuring that the display is ready to receive and apply the new TFT file without needing
|
||||
* to manually reset or reconfigure. Exiting reparse mode is recommended for most upload scenarios to ensure
|
||||
* the display properly processes the uploaded file command.
|
||||
* @return bool True: Transfer completed successfuly, False: Transfer failed.
|
||||
*/
|
||||
bool upload_tft(uint32_t baud_rate = 0, bool exit_reparse = true);
|
||||
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
bool upload_tft(bool exit_reparse = true);
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
@@ -1136,13 +1122,11 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
void all_components_send_state_(bool force_update = false);
|
||||
uint64_t comok_sent_ = 0;
|
||||
bool remove_from_q_(bool report_empty = true);
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Sends commands ignoring of the Nextion has been setup.
|
||||
*/
|
||||
bool ignore_is_setup_ = false;
|
||||
|
||||
bool nextion_reports_is_setup_ = false;
|
||||
uint8_t nextion_event_;
|
||||
|
||||
@@ -1179,37 +1163,41 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
void check_pending_waveform_();
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ESP8266
|
||||
WiFiClient *wifi_client_{nullptr};
|
||||
BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr};
|
||||
WiFiClient *get_wifi_client_();
|
||||
#endif // USE_ESP8266
|
||||
std::string tft_url_;
|
||||
uint32_t content_length_ = 0;
|
||||
int tft_size_ = 0;
|
||||
uint32_t original_baud_rate_ = 0;
|
||||
bool upload_first_chunk_sent_ = false;
|
||||
|
||||
#ifdef USE_ARDUINO
|
||||
std::string tft_url_;
|
||||
uint8_t *transfer_buffer_{nullptr};
|
||||
size_t transfer_buffer_size_;
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
WiFiClient *wifi_client_{nullptr};
|
||||
BearSSL::WiFiClientSecure *wifi_client_secure_{nullptr};
|
||||
WiFiClient *get_wifi_client_();
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO
|
||||
/**
|
||||
* will request chunk_size chunks from the web server
|
||||
* and send each to the nextion
|
||||
* @param HTTPClient http_client HTTP client handler.
|
||||
* @param HTTPClient http HTTP client handler.
|
||||
* @param int range_start Position of next byte to transfer.
|
||||
* @return position of last byte transferred, -1 for failure.
|
||||
*/
|
||||
int upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start);
|
||||
#elif defined(USE_ESP_IDF)
|
||||
/**
|
||||
* will request 4096 bytes chunks from the web server
|
||||
* and send each to Nextion
|
||||
* @param esp_http_client_handle_t http_client HTTP client handler.
|
||||
* @param int range_start Position of next byte to transfer.
|
||||
* @return position of last byte transferred, -1 for failure.
|
||||
*/
|
||||
int upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start);
|
||||
#endif // USE_ARDUINO vs USE_ESP_IDF
|
||||
int upload_by_chunks_(HTTPClient *http, int range_start);
|
||||
|
||||
bool upload_with_range_(uint32_t range_start, uint32_t range_end);
|
||||
|
||||
/**
|
||||
* start update tft file to nextion.
|
||||
*
|
||||
* @param const uint8_t *file_buf
|
||||
* @param size_t buf_size
|
||||
* @return true if success, false for failure.
|
||||
*/
|
||||
bool upload_from_buffer_(const uint8_t *file_buf, size_t buf_size);
|
||||
/**
|
||||
* Ends the upload process, restart Nextion and, if successful,
|
||||
* restarts ESP
|
||||
@@ -1217,12 +1205,23 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
* @return bool True: Transfer completed successfuly, False: Transfer failed.
|
||||
*/
|
||||
bool upload_end_(bool successful);
|
||||
|
||||
#elif defined(USE_ESP_IDF)
|
||||
/**
|
||||
* Returns the ESP Free Heap memory. This is framework independent.
|
||||
* @return Free Heap in bytes.
|
||||
* will request 4096 bytes chunks from the web server
|
||||
* and send each to Nextion
|
||||
* @param std::string url Full url for download.
|
||||
* @param int range_start Position of next byte to transfer.
|
||||
* @return position of last byte transferred, -1 for failure.
|
||||
*/
|
||||
uint32_t get_free_heap_();
|
||||
int upload_range(const std::string &url, int range_start);
|
||||
/**
|
||||
* Ends the upload process, restart Nextion and, if successful,
|
||||
* restarts ESP
|
||||
* @param bool url successful True: Transfer completed successfuly, False: Transfer failed.
|
||||
* @return bool True: Transfer completed successfuly, False: Transfer failed.
|
||||
*/
|
||||
bool upload_end(bool successful);
|
||||
#endif // ARDUINO vs ESP-IDF
|
||||
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
|
||||
@@ -1253,7 +1252,7 @@ class Nextion : public NextionBase, public PollingComponent, public uart::UARTDe
|
||||
|
||||
#ifdef NEXTION_PROTOCOL_LOG
|
||||
void print_queue_members_();
|
||||
#endif // NEXTION_PROTOCOL_LOG
|
||||
#endif
|
||||
void reset_(bool reset_nextion = true);
|
||||
|
||||
std::string command_data_;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
#include "nextion.h"
|
||||
|
||||
#ifdef ARDUINO
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ARDUINO
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/network/util.h"
|
||||
#include <cinttypes>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
#include <esp_heap_caps.h>
|
||||
@@ -21,147 +20,139 @@ static const char *const TAG = "nextion.upload.arduino";
|
||||
// Followed guide
|
||||
// https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2
|
||||
|
||||
inline uint32_t Nextion::get_free_heap_() {
|
||||
#if defined(USE_ESP32)
|
||||
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
#elif defined(USE_ESP8266)
|
||||
return EspClass::getFreeHeap();
|
||||
#endif // USE_ESP32 vs USE_ESP8266
|
||||
}
|
||||
int Nextion::upload_by_chunks_(HTTPClient *http, int range_start) {
|
||||
int range_end = 0;
|
||||
|
||||
int Nextion::upload_by_chunks_(HTTPClient &http_client, uint32_t &range_start) {
|
||||
uint32_t range_size = this->tft_size_ - range_start;
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1;
|
||||
ESP_LOGD(TAG, "Range start: %" PRIu32, range_start);
|
||||
if (range_size <= 0 or range_end <= range_start) {
|
||||
ESP_LOGD(TAG, "Range end: %" PRIu32, range_end);
|
||||
ESP_LOGD(TAG, "Range size: %" PRIu32, range_size);
|
||||
ESP_LOGE(TAG, "Invalid range");
|
||||
return -1;
|
||||
if (range_start == 0 && this->transfer_buffer_size_ > 16384) { // Start small at the first run in case of a big skip
|
||||
range_end = 16384 - 1;
|
||||
} else {
|
||||
range_end = range_start + this->transfer_buffer_size_ - 1;
|
||||
}
|
||||
|
||||
char range_header[32];
|
||||
sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end);
|
||||
ESP_LOGV(TAG, "Requesting range: %s", range_header);
|
||||
http_client.addHeader("Range", range_header);
|
||||
int code = http_client.GET();
|
||||
if (code != HTTP_CODE_OK and code != HTTP_CODE_PARTIAL_CONTENT) {
|
||||
ESP_LOGW(TAG, "HTTP Request failed; Error: %s", HTTPClient::errorToString(code).c_str());
|
||||
return -1;
|
||||
if (range_end > this->tft_size_)
|
||||
range_end = this->tft_size_;
|
||||
|
||||
#ifdef USE_ESP8266
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
|
||||
http->setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
#elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http->setFollowRedirects(true);
|
||||
#endif
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http->setRedirectLimit(3);
|
||||
#endif
|
||||
#endif // USE_ESP8266
|
||||
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%d-%d", range_start, range_end);
|
||||
|
||||
ESP_LOGD(TAG, "Requesting range: %s", range_header);
|
||||
|
||||
int tries = 1;
|
||||
int code = 0;
|
||||
bool begin_status = false;
|
||||
while (tries <= 5) {
|
||||
#ifdef USE_ESP32
|
||||
begin_status = http->begin(this->tft_url_.c_str());
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
begin_status = http->begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif
|
||||
|
||||
++tries;
|
||||
if (!begin_status) {
|
||||
ESP_LOGD(TAG, "upload_by_chunks_: connection failed");
|
||||
delay(500); // NOLINT
|
||||
continue;
|
||||
}
|
||||
|
||||
http->addHeader("Range", range_header);
|
||||
|
||||
code = http->GET();
|
||||
if (code == 200 || code == 206) {
|
||||
break;
|
||||
}
|
||||
ESP_LOGW(TAG, "HTTP Request failed; URL: %s; Error: %s, retries(%d/5)", this->tft_url_.c_str(),
|
||||
HTTPClient::errorToString(code).c_str(), tries);
|
||||
http->end();
|
||||
App.feed_wdt();
|
||||
delay(500); // NOLINT
|
||||
}
|
||||
|
||||
// Allocate the buffer dynamically
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
uint8_t *buffer = allocator.allocate(4096);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "Failed to allocate upload buffer");
|
||||
if (tries > 5) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::string recv_string;
|
||||
while (true) {
|
||||
App.feed_wdt();
|
||||
const uint16_t buffer_size =
|
||||
this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data
|
||||
ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size);
|
||||
uint16_t read_len = 0;
|
||||
int partial_read_len = 0;
|
||||
const uint32_t start_time = millis();
|
||||
while (read_len < buffer_size && millis() - start_time < 5000) {
|
||||
if (http_client.getStreamPtr()->available() > 0) {
|
||||
partial_read_len =
|
||||
http_client.getStreamPtr()->readBytes(reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
|
||||
read_len += partial_read_len;
|
||||
if (partial_read_len > 0) {
|
||||
App.feed_wdt();
|
||||
delay(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (read_len != buffer_size) {
|
||||
// Did not receive the full package within the timeout period
|
||||
ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len,
|
||||
buffer_size);
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len);
|
||||
if (read_len > 0) {
|
||||
recv_string.clear();
|
||||
this->write_array(buffer, buffer_size);
|
||||
App.feed_wdt();
|
||||
this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true);
|
||||
this->content_length_ -= read_len;
|
||||
const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_;
|
||||
#if defined(USE_ESP32) && defined(USE_PSRAM)
|
||||
ESP_LOGD(
|
||||
TAG,
|
||||
"Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes",
|
||||
upload_percentage, this->content_length_, static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)),
|
||||
static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)));
|
||||
#else
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage,
|
||||
this->content_length_, this->get_free_heap_());
|
||||
#endif
|
||||
upload_first_chunk_sent_ = true;
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request
|
||||
ESP_LOGD(TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
range_start = result;
|
||||
} else {
|
||||
range_start = range_end + 1;
|
||||
}
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return range_end + 1;
|
||||
} else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok"
|
||||
ESP_LOGE(TAG, "Invalid response from Nextion: [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
size_t size = 0;
|
||||
int fetched = 0;
|
||||
int range = range_end - range_start;
|
||||
|
||||
recv_string.clear();
|
||||
} else if (read_len == 0) {
|
||||
ESP_LOGV(TAG, "End of HTTP response reached");
|
||||
break; // Exit the loop if there is no more data to read
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len);
|
||||
break; // Exit the loop on error
|
||||
while (fetched < range) {
|
||||
size = http->getStreamPtr()->available();
|
||||
if (!size) {
|
||||
App.feed_wdt();
|
||||
delay(0);
|
||||
continue;
|
||||
}
|
||||
int c = http->getStreamPtr()->readBytes(
|
||||
&this->transfer_buffer_[fetched], ((size > this->transfer_buffer_size_) ? this->transfer_buffer_size_ : size));
|
||||
fetched += c;
|
||||
}
|
||||
range_start = range_end + 1;
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
http->end();
|
||||
ESP_LOGN(TAG, "Fetched %d of %d bytes", fetched, this->content_length_);
|
||||
|
||||
// upload fetched segments to the display in 4KB chunks
|
||||
int write_len;
|
||||
for (int i = 0; i < range; i += 4096) {
|
||||
App.feed_wdt();
|
||||
write_len = this->content_length_ < 4096 ? this->content_length_ : 4096;
|
||||
this->write_array(&this->transfer_buffer_[i], write_len);
|
||||
this->content_length_ -= write_len;
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f %%; %d bytes remaining",
|
||||
100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_);
|
||||
|
||||
if (!this->upload_first_chunk_sent_) {
|
||||
this->upload_first_chunk_sent_ = true;
|
||||
delay(500); // NOLINT
|
||||
}
|
||||
|
||||
this->recv_ret_string_(recv_string, 4096, true);
|
||||
if (recv_string[0] != 0x05) { // 0x05 == "ok"
|
||||
ESP_LOGD(TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
}
|
||||
|
||||
// handle partial upload request
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) {
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGD(TAG, "Nextion reported new range %d", result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
recv_string.clear();
|
||||
}
|
||||
|
||||
return range_end + 1;
|
||||
}
|
||||
|
||||
bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
bool Nextion::upload_tft(bool exit_reparse) {
|
||||
ESP_LOGD(TAG, "Nextion TFT upload requested");
|
||||
ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse));
|
||||
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
|
||||
|
||||
if (this->is_updating_) {
|
||||
ESP_LOGW(TAG, "Currently uploading");
|
||||
ESP_LOGD(TAG, "Currently updating");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!network::is_connected()) {
|
||||
ESP_LOGE(TAG, "Network is not connected");
|
||||
ESP_LOGD(TAG, "network is not connected");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -175,51 +166,43 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if baud rate is supported
|
||||
this->original_baud_rate_ = this->parent_->get_baud_rate();
|
||||
static const std::vector<uint32_t> SUPPORTED_BAUD_RATES = {2400, 4800, 9600, 19200, 31250, 38400, 57600,
|
||||
115200, 230400, 250000, 256000, 512000, 921600};
|
||||
if (std::find(SUPPORTED_BAUD_RATES.begin(), SUPPORTED_BAUD_RATES.end(), baud_rate) == SUPPORTED_BAUD_RATES.end()) {
|
||||
baud_rate = this->original_baud_rate_;
|
||||
}
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG, "Initializing HTTP client");
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
HTTPClient http_client;
|
||||
http_client.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
|
||||
HTTPClient http;
|
||||
http.setTimeout(15000); // Yes 15 seconds.... Helps 8266s along
|
||||
bool begin_status = false;
|
||||
#ifdef USE_ESP32
|
||||
begin_status = http_client.begin(this->tft_url_.c_str());
|
||||
begin_status = http.begin(this->tft_url_.c_str());
|
||||
#endif
|
||||
#ifdef USE_ESP8266
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 7, 0)
|
||||
http_client.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
|
||||
#elif USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http_client.setFollowRedirects(true);
|
||||
http.setFollowRedirects(true);
|
||||
#endif
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 6, 0)
|
||||
http_client.setRedirectLimit(3);
|
||||
http.setRedirectLimit(3);
|
||||
#endif
|
||||
begin_status = http_client.begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif // USE_ESP8266
|
||||
begin_status = http.begin(*this->get_wifi_client_(), this->tft_url_.c_str());
|
||||
#endif
|
||||
|
||||
if (!begin_status) {
|
||||
this->is_updating_ = false;
|
||||
ESP_LOGD(TAG, "Connection failed");
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
allocator.deallocate(this->transfer_buffer_, this->transfer_buffer_size_);
|
||||
return false;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Connected");
|
||||
}
|
||||
http_client.addHeader("Range", "bytes=0-255");
|
||||
|
||||
http.addHeader("Range", "bytes=0-255");
|
||||
const char *header_names[] = {"Content-Range"};
|
||||
http_client.collectHeaders(header_names, 1);
|
||||
http.collectHeaders(header_names, 1);
|
||||
ESP_LOGD(TAG, "Requesting URL: %s", this->tft_url_.c_str());
|
||||
http_client.setReuse(true);
|
||||
|
||||
http.setReuse(true);
|
||||
// try up to 5 times. DNS sometimes needs a second try or so
|
||||
int tries = 1;
|
||||
int code = http_client.GET();
|
||||
int code = http.GET();
|
||||
delay(100); // NOLINT
|
||||
|
||||
App.feed_wdt();
|
||||
@@ -229,133 +212,135 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
|
||||
delay(250); // NOLINT
|
||||
App.feed_wdt();
|
||||
code = http_client.GET();
|
||||
code = http.GET();
|
||||
++tries;
|
||||
}
|
||||
|
||||
if (code != 200 and code != 206) {
|
||||
if ((code != 200 && code != 206) || tries > 5) {
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
String content_range_string = http_client.header("Content-Range");
|
||||
String content_range_string = http.header("Content-Range");
|
||||
content_range_string.remove(0, 12);
|
||||
this->tft_size_ = content_range_string.toInt();
|
||||
this->content_length_ = content_range_string.toInt();
|
||||
this->tft_size_ = content_length_;
|
||||
http.end();
|
||||
|
||||
ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_);
|
||||
if (this->tft_size_ < 4096) {
|
||||
ESP_LOGE(TAG, "File size check failed.");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
if (this->content_length_ < 4096) {
|
||||
ESP_LOGE(TAG, "Failed to get file size");
|
||||
return this->upload_end_(false);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding...");
|
||||
}
|
||||
this->content_length_ = this->tft_size_;
|
||||
|
||||
ESP_LOGD(TAG, "Uploading Nextion");
|
||||
ESP_LOGD(TAG, "Updating Nextion %s...", this->device_model_.c_str());
|
||||
// The Nextion will ignore the update command if it is sleeping
|
||||
|
||||
// The Nextion will ignore the upload command if it is sleeping
|
||||
ESP_LOGV(TAG, "Wake-up Nextion");
|
||||
this->ignore_is_setup_ = true;
|
||||
this->send_command_("sleep=0");
|
||||
this->send_command_("dim=100");
|
||||
this->set_backlight_brightness(1.0);
|
||||
delay(250); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
App.feed_wdt();
|
||||
|
||||
char command[128];
|
||||
// Tells the Nextion the content length of the tft file and baud rate it will be sent at
|
||||
// Once the Nextion accepts the command it will wait until the file is successfully uploaded
|
||||
// If it fails for any reason a power cycle of the display will be needed
|
||||
sprintf(command, "whmi-wris %d,%d,1", this->content_length_, baud_rate);
|
||||
sprintf(command, "whmi-wris %d,%d,1", this->content_length_, this->parent_->get_baud_rate());
|
||||
|
||||
// Clear serial receive buffer
|
||||
ESP_LOGV(TAG, "Clear serial receive buffer");
|
||||
this->reset_(false);
|
||||
delay(250); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
uint8_t d;
|
||||
while (this->available()) {
|
||||
this->read_byte(&d);
|
||||
};
|
||||
|
||||
ESP_LOGV(TAG, "Send upload instruction: %s", command);
|
||||
this->send_command_(command);
|
||||
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Changing baud rate from %" PRIu32 " to %" PRIu32 " bps", this->original_baud_rate_, baud_rate);
|
||||
this->parent_->set_baud_rate(baud_rate);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
|
||||
App.feed_wdt();
|
||||
|
||||
std::string response;
|
||||
ESP_LOGV(TAG, "Waiting for upgrade response");
|
||||
this->recv_ret_string_(response, 5000, true); // This can take some time to return
|
||||
ESP_LOGD(TAG, "Waiting for upgrade response");
|
||||
this->recv_ret_string_(response, 2000, true); // This can take some time to return
|
||||
|
||||
// The Nextion display will, if it's ready to accept data, send a 0x05 byte.
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)",
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
|
||||
response.length());
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, this->get_free_heap_());
|
||||
|
||||
for (size_t i = 0; i < response.length(); i++) {
|
||||
ESP_LOGD(TAG, "Available %d : 0x%02X", i, response[i]);
|
||||
}
|
||||
|
||||
if (response.find(0x05) != std::string::npos) {
|
||||
ESP_LOGV(TAG, "Preparation for TFT upload done");
|
||||
ESP_LOGD(TAG, "preparation for tft update done");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str());
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
ESP_LOGD(TAG, "preparation for tft update failed %d \"%s\"", response[0], response.c_str());
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Uploading TFT to Nextion:");
|
||||
ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, " File size: %d bytes", this->content_length_);
|
||||
ESP_LOGD(TAG, " Free heap: %" PRIu32, this->get_free_heap_());
|
||||
// Nextion wants 4096 bytes at a time. Make chunk_size a multiple of 4096
|
||||
#ifdef USE_ESP32
|
||||
uint32_t chunk_size = 8192;
|
||||
if (heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0) {
|
||||
chunk_size = this->content_length_;
|
||||
} else {
|
||||
if (ESP.getFreeHeap() > 81920) { // Ensure some FreeHeap to other things and limit chunk size
|
||||
chunk_size = ESP.getFreeHeap() - 65536;
|
||||
chunk_size = int(chunk_size / 4096) * 4096;
|
||||
chunk_size = chunk_size > 65536 ? 65536 : chunk_size;
|
||||
} else if (ESP.getFreeHeap() < 32768) {
|
||||
chunk_size = 4096;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
uint32_t chunk_size = ESP.getFreeHeap() < 16384 ? 4096 : 8192;
|
||||
#endif
|
||||
|
||||
// Proceed with the content download as before
|
||||
if (this->transfer_buffer_ == nullptr) {
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Allocating buffer size %d, Heap size is %u", chunk_size, ESP.getFreeHeap());
|
||||
this->transfer_buffer_ = allocator.allocate(chunk_size);
|
||||
if (this->transfer_buffer_ == nullptr) { // Try a smaller size
|
||||
ESP_LOGD(TAG, "Could not allocate buffer size: %d trying 4096 instead", chunk_size);
|
||||
chunk_size = 4096;
|
||||
ESP_LOGD(TAG, "Allocating %d buffer", chunk_size);
|
||||
this->transfer_buffer_ = allocator.allocate(chunk_size);
|
||||
|
||||
ESP_LOGV(TAG, "Starting transfer by chunks loop");
|
||||
if (!this->transfer_buffer_)
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
uint32_t position = 0;
|
||||
this->transfer_buffer_size_ = chunk_size;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d using %zu chunksize, Heap Size %d",
|
||||
this->tft_url_.c_str(), this->content_length_, this->transfer_buffer_size_, ESP.getFreeHeap());
|
||||
|
||||
int result = 0;
|
||||
while (this->content_length_ > 0) {
|
||||
int upload_result = upload_by_chunks_(http_client, position);
|
||||
if (upload_result < 0) {
|
||||
ESP_LOGE(TAG, "Error uploading TFT to Nextion!");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
result = this->upload_by_chunks_(&http, result);
|
||||
if (result < 0) {
|
||||
ESP_LOGD(TAG, "Error updating Nextion!");
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
App.feed_wdt();
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, this->get_free_heap_(), this->content_length_);
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
ESP_LOGD(TAG, "Heap Size %d, Bytes left %d", ESP.getFreeHeap(), this->content_length_);
|
||||
}
|
||||
ESP_LOGD(TAG, "Successfully updated Nextion!");
|
||||
|
||||
ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!");
|
||||
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
http_client.end();
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return upload_end_(true);
|
||||
return this->upload_end_(true);
|
||||
}
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful));
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Changing baud rate back from %" PRIu32 " to %" PRIu32 " bps", baud_rate, this->original_baud_rate_);
|
||||
this->parent_->set_baud_rate(this->original_baud_rate_);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Restarting Nextion");
|
||||
this->soft_reset();
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Restarting ESPHome");
|
||||
delay(1500); // NOLINT
|
||||
arch_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Nextion TFT upload failed");
|
||||
ESP_LOGD(TAG, "Restarting esphome");
|
||||
ESP.restart(); // NOLINT(readability-static-accessed-through-instance)
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
@@ -378,10 +363,9 @@ WiFiClient *Nextion::get_wifi_client_() {
|
||||
}
|
||||
return this->wifi_client_;
|
||||
}
|
||||
#endif // USE_ESP8266
|
||||
|
||||
#endif
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ARDUINO
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
#endif // ARDUINO
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
#include "nextion.h"
|
||||
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
#ifdef USE_ESP_IDF
|
||||
#ifdef USE_NEXTION_TFT_UPLOAD
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#include "esphome/core/util.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/components/network/util.h"
|
||||
#include <cinttypes>
|
||||
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_http_client.h>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace esphome {
|
||||
namespace nextion {
|
||||
@@ -19,147 +20,153 @@ static const char *const TAG = "nextion.upload.idf";
|
||||
// Followed guide
|
||||
// https://unofficialnextion.com/t/nextion-upload-protocol-v1-2-the-fast-one/1044/2
|
||||
|
||||
int Nextion::upload_by_chunks_(esp_http_client_handle_t http_client, uint32_t &range_start) {
|
||||
uint32_t range_size = this->tft_size_ - range_start;
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
uint32_t range_end = ((upload_first_chunk_sent_ or this->tft_size_ < 4096) ? this->tft_size_ : 4096) - 1;
|
||||
ESP_LOGD(TAG, "Range start: %" PRIu32, range_start);
|
||||
int Nextion::upload_range(const std::string &url, int range_start) {
|
||||
ESP_LOGVV(TAG, "url: %s", url.c_str());
|
||||
uint range_size = this->tft_size_ - range_start;
|
||||
ESP_LOGVV(TAG, "tft_size_: %i", this->tft_size_);
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int range_end = (range_start == 0) ? std::min(this->tft_size_, 16383) : this->tft_size_;
|
||||
if (range_size <= 0 or range_end <= range_start) {
|
||||
ESP_LOGD(TAG, "Range end: %" PRIu32, range_end);
|
||||
ESP_LOGD(TAG, "Range size: %" PRIu32, range_size);
|
||||
ESP_LOGE(TAG, "Invalid range");
|
||||
ESP_LOGD(TAG, "Range start: %i", range_start);
|
||||
ESP_LOGD(TAG, "Range end: %i", range_end);
|
||||
ESP_LOGD(TAG, "Range size: %i", range_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char range_header[32];
|
||||
sprintf(range_header, "bytes=%" PRIu32 "-%" PRIu32, range_start, range_end);
|
||||
esp_http_client_config_t config = {
|
||||
.url = url.c_str(),
|
||||
.cert_pem = nullptr,
|
||||
.disable_auto_redirect = false,
|
||||
.max_redirection_count = 10,
|
||||
};
|
||||
esp_http_client_handle_t client = esp_http_client_init(&config);
|
||||
|
||||
char range_header[64];
|
||||
sprintf(range_header, "bytes=%d-%d", range_start, range_end);
|
||||
ESP_LOGV(TAG, "Requesting range: %s", range_header);
|
||||
esp_http_client_set_header(http_client, "Range", range_header);
|
||||
ESP_LOGV(TAG, "Opening HTTP connetion");
|
||||
esp_http_client_set_header(client, "Range", range_header);
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
|
||||
ESP_LOGV(TAG, "Opening http connetion");
|
||||
esp_err_t err;
|
||||
if ((err = esp_http_client_open(http_client, 0)) != ESP_OK) {
|
||||
if ((err = esp_http_client_open(client, 0)) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection: %s", esp_err_to_name(err));
|
||||
esp_http_client_cleanup(client);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Fetch content length");
|
||||
const int chunk_size = esp_http_client_fetch_headers(http_client);
|
||||
ESP_LOGV(TAG, "content_length = %d", chunk_size);
|
||||
if (chunk_size <= 0) {
|
||||
ESP_LOGE(TAG, "Failed to get chunk's content length: %d", chunk_size);
|
||||
int content_length = esp_http_client_fetch_headers(client);
|
||||
ESP_LOGV(TAG, "content_length = %d", content_length);
|
||||
if (content_length <= 0) {
|
||||
ESP_LOGE(TAG, "Failed to get content length: %d", content_length);
|
||||
esp_http_client_cleanup(client);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Allocate the buffer dynamically
|
||||
ExternalRAMAllocator<uint8_t> allocator(ExternalRAMAllocator<uint8_t>::ALLOW_FAILURE);
|
||||
uint8_t *buffer = allocator.allocate(4096);
|
||||
if (!buffer) {
|
||||
ESP_LOGE(TAG, "Failed to allocate upload buffer");
|
||||
return -1;
|
||||
}
|
||||
int total_read_len = 0, read_len;
|
||||
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Allocate buffer");
|
||||
uint8_t *buffer = new uint8_t[4096];
|
||||
std::string recv_string;
|
||||
while (true) {
|
||||
App.feed_wdt();
|
||||
const uint16_t buffer_size =
|
||||
this->content_length_ < 4096 ? this->content_length_ : 4096; // Limits buffer to the remaining data
|
||||
ESP_LOGV(TAG, "Fetching %" PRIu16 " bytes from HTTP", buffer_size);
|
||||
uint16_t read_len = 0;
|
||||
int partial_read_len = 0;
|
||||
uint8_t retries = 0;
|
||||
// Attempt to read the chunk with retries.
|
||||
while (retries < 5 && read_len < buffer_size) {
|
||||
partial_read_len =
|
||||
esp_http_client_read(http_client, reinterpret_cast<char *>(buffer) + read_len, buffer_size - read_len);
|
||||
if (partial_read_len > 0) {
|
||||
read_len += partial_read_len; // Accumulate the total read length.
|
||||
// Reset retries on successful read.
|
||||
retries = 0;
|
||||
} else {
|
||||
// If no data was read, increment retries.
|
||||
retries++;
|
||||
vTaskDelay(pdMS_TO_TICKS(2)); // NOLINT
|
||||
}
|
||||
App.feed_wdt(); // Feed the watchdog timer.
|
||||
}
|
||||
if (read_len != buffer_size) {
|
||||
// Did not receive the full package within the timeout period
|
||||
ESP_LOGE(TAG, "Failed to read full package, received only %" PRIu16 " of %" PRIu16 " bytes", read_len,
|
||||
buffer_size);
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGV(TAG, "%d bytes fetched, writing it to UART", read_len);
|
||||
if (read_len > 0) {
|
||||
recv_string.clear();
|
||||
this->write_array(buffer, buffer_size);
|
||||
App.feed_wdt();
|
||||
this->recv_ret_string_(recv_string, upload_first_chunk_sent_ ? 500 : 5000, true);
|
||||
this->content_length_ -= read_len;
|
||||
const float upload_percentage = 100.0f * (this->tft_size_ - this->content_length_) / this->tft_size_;
|
||||
#ifdef USE_PSRAM
|
||||
ESP_LOGD(
|
||||
TAG,
|
||||
"Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " (DRAM) + %" PRIu32 " (PSRAM) bytes",
|
||||
upload_percentage, this->content_length_, static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_INTERNAL)),
|
||||
static_cast<uint32_t>(heap_caps_get_free_size(MALLOC_CAP_SPIRAM)));
|
||||
#else
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f%%, remaining %" PRIu32 " bytes, free heap: %" PRIu32 " bytes", upload_percentage,
|
||||
this->content_length_, static_cast<uint32_t>(esp_get_free_heap_size()));
|
||||
#endif
|
||||
upload_first_chunk_sent_ = true;
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request
|
||||
ESP_LOGD(TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
range_start = result;
|
||||
} else {
|
||||
range_start = range_end + 1;
|
||||
}
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return range_end + 1;
|
||||
} else if (recv_string[0] != 0x05 and recv_string[0] != 0x08) { // 0x05 == "ok"
|
||||
ESP_LOGE(TAG, "Invalid response from Nextion: [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
return -1;
|
||||
}
|
||||
if (buffer == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for buffer");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Memory for buffer allocated successfully");
|
||||
|
||||
recv_string.clear();
|
||||
} else if (read_len == 0) {
|
||||
ESP_LOGV(TAG, "End of HTTP response reached");
|
||||
break; // Exit the loop if there is no more data to read
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %" PRIu16, read_len);
|
||||
break; // Exit the loop on error
|
||||
while (true) {
|
||||
App.feed_wdt();
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int read_len = esp_http_client_read(client, reinterpret_cast<char *>(buffer), 4096);
|
||||
ESP_LOGVV(TAG, "Read %d bytes from HTTP client, writing to UART", read_len);
|
||||
if (read_len > 0) {
|
||||
this->write_array(buffer, read_len);
|
||||
ESP_LOGVV(TAG, "Write to UART successful");
|
||||
this->recv_ret_string_(recv_string, 5000, true);
|
||||
this->content_length_ -= read_len;
|
||||
ESP_LOGD(TAG, "Uploaded %0.2f %%, remaining %d bytes, heap is %" PRIu32 " bytes",
|
||||
100.0 * (this->tft_size_ - this->content_length_) / this->tft_size_, this->content_length_,
|
||||
esp_get_free_heap_size());
|
||||
|
||||
if (recv_string[0] == 0x08 && recv_string.size() == 5) { // handle partial upload request
|
||||
ESP_LOGD(
|
||||
TAG, "recv_string [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
uint32_t result = 0;
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
result += static_cast<uint8_t>(recv_string[j + 1]) << (8 * j);
|
||||
}
|
||||
if (result > 0) {
|
||||
ESP_LOGI(TAG, "Nextion reported new range %" PRIu32, result);
|
||||
this->content_length_ = this->tft_size_ - result;
|
||||
// Deallocate the buffer when done
|
||||
ESP_LOGV(TAG, "Deallocate buffer");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
delete[] buffer;
|
||||
ESP_LOGVV(TAG, "Memory for buffer deallocated");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Close http client");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_close(client);
|
||||
esp_http_client_cleanup(client);
|
||||
ESP_LOGVV(TAG, "Client closed");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
return result;
|
||||
}
|
||||
} else if (recv_string[0] != 0x05) { // 0x05 == "ok"
|
||||
ESP_LOGE(
|
||||
TAG, "Invalid response from Nextion: [%s]",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(recv_string.data()), recv_string.size()).c_str());
|
||||
ESP_LOGV(TAG, "Deallocate buffer");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
delete[] buffer;
|
||||
ESP_LOGVV(TAG, "Memory for buffer deallocated");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Close http client");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_close(client);
|
||||
esp_http_client_cleanup(client);
|
||||
ESP_LOGVV(TAG, "Client closed");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
return -1;
|
||||
}
|
||||
|
||||
recv_string.clear();
|
||||
} else if (read_len == 0) {
|
||||
ESP_LOGV(TAG, "End of HTTP response reached");
|
||||
break; // Exit the loop if there is no more data to read
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to read from HTTP client, error code: %d", read_len);
|
||||
break; // Exit the loop on error
|
||||
}
|
||||
}
|
||||
|
||||
// Deallocate the buffer when done
|
||||
ESP_LOGV(TAG, "Deallocate buffer");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
delete[] buffer;
|
||||
ESP_LOGVV(TAG, "Memory for buffer deallocated");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
}
|
||||
range_start = range_end + 1;
|
||||
// Deallocate buffer
|
||||
allocator.deallocate(buffer, 4096);
|
||||
buffer = nullptr;
|
||||
ESP_LOGV(TAG, "Close http client");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_close(client);
|
||||
esp_http_client_cleanup(client);
|
||||
ESP_LOGVV(TAG, "Client closed");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
return range_end + 1;
|
||||
}
|
||||
|
||||
bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
bool Nextion::upload_tft(bool exit_reparse) {
|
||||
ESP_LOGD(TAG, "Nextion TFT upload requested");
|
||||
ESP_LOGD(TAG, "Exit reparse: %s", YESNO(exit_reparse));
|
||||
ESP_LOGD(TAG, "URL: %s", this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, "url: %s", this->tft_url_.c_str());
|
||||
|
||||
if (this->is_updating_) {
|
||||
ESP_LOGW(TAG, "Currently uploading");
|
||||
ESP_LOGW(TAG, "Currently updating");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -178,18 +185,9 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if baud rate is supported
|
||||
this->original_baud_rate_ = this->parent_->get_baud_rate();
|
||||
static const std::vector<uint32_t> SUPPORTED_BAUD_RATES = {2400, 4800, 9600, 19200, 31250, 38400, 57600,
|
||||
115200, 230400, 250000, 256000, 512000, 921600};
|
||||
if (std::find(SUPPORTED_BAUD_RATES.begin(), SUPPORTED_BAUD_RATES.end(), baud_rate) == SUPPORTED_BAUD_RATES.end()) {
|
||||
baud_rate = this->original_baud_rate_;
|
||||
}
|
||||
ESP_LOGD(TAG, "Baud rate: %" PRIu32, baud_rate);
|
||||
|
||||
// Define the configuration for the HTTP client
|
||||
ESP_LOGV(TAG, "Initializing HTTP client");
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGV(TAG, "Establishing connection to HTTP server");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_config_t config = {
|
||||
.url = this->tft_url_.c_str(),
|
||||
.cert_pem = nullptr,
|
||||
@@ -198,164 +196,124 @@ bool Nextion::upload_tft(uint32_t baud_rate, bool exit_reparse) {
|
||||
.disable_auto_redirect = false,
|
||||
.max_redirection_count = 10,
|
||||
};
|
||||
// Initialize the HTTP client with the configuration
|
||||
esp_http_client_handle_t http_client = esp_http_client_init(&config);
|
||||
if (!http_client) {
|
||||
ESP_LOGE(TAG, "Failed to initialize HTTP client.");
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
esp_err_t err = esp_http_client_set_header(http_client, "Connection", "keep-alive");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "HTTP set header failed: %s", esp_err_to_name(err));
|
||||
esp_http_client_cleanup(http_client);
|
||||
return this->upload_end_(false);
|
||||
// Initialize the HTTP client with the configuration
|
||||
ESP_LOGV(TAG, "Initializing HTTP client");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_handle_t http = esp_http_client_init(&config);
|
||||
if (!http) {
|
||||
ESP_LOGE(TAG, "Failed to initialize HTTP client.");
|
||||
return this->upload_end(false);
|
||||
}
|
||||
|
||||
// Perform the HTTP request
|
||||
ESP_LOGV(TAG, "Check if the client could connect");
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
err = esp_http_client_perform(http_client);
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_err_t err = esp_http_client_perform(http);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "HTTP request failed: %s", esp_err_to_name(err));
|
||||
esp_http_client_cleanup(http_client);
|
||||
return this->upload_end_(false);
|
||||
esp_http_client_cleanup(http);
|
||||
return this->upload_end(false);
|
||||
}
|
||||
|
||||
// Check the HTTP Status Code
|
||||
ESP_LOGV(TAG, "Check the HTTP Status Code");
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int status_code = esp_http_client_get_status_code(http_client);
|
||||
if (status_code != 200 && status_code != 206) {
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int status_code = esp_http_client_get_status_code(http);
|
||||
ESP_LOGV(TAG, "HTTP Status Code: %d", status_code);
|
||||
size_t tft_file_size = esp_http_client_get_content_length(http);
|
||||
ESP_LOGD(TAG, "TFT file size: %zu", tft_file_size);
|
||||
|
||||
this->tft_size_ = esp_http_client_get_content_length(http_client);
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
esp_http_client_close(http);
|
||||
esp_http_client_cleanup(http);
|
||||
ESP_LOGVV(TAG, "Connection closed");
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
|
||||
ESP_LOGD(TAG, "TFT file size: %zu bytes", this->tft_size_);
|
||||
if (this->tft_size_ < 4096 || this->tft_size_ > 134217728) {
|
||||
ESP_LOGE(TAG, "File size check failed.");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
esp_http_client_close(http_client);
|
||||
esp_http_client_cleanup(http_client);
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
if (tft_file_size < 4096) {
|
||||
ESP_LOGE(TAG, "File size check failed. Size: %zu", tft_file_size);
|
||||
return this->upload_end(false);
|
||||
} else {
|
||||
ESP_LOGV(TAG, "File size check passed. Proceeding...");
|
||||
}
|
||||
this->content_length_ = this->tft_size_;
|
||||
this->content_length_ = tft_file_size;
|
||||
this->tft_size_ = tft_file_size;
|
||||
|
||||
ESP_LOGD(TAG, "Uploading Nextion");
|
||||
ESP_LOGD(TAG, "Updating Nextion");
|
||||
|
||||
// The Nextion will ignore the upload command if it is sleeping
|
||||
// The Nextion will ignore the update command if it is sleeping
|
||||
ESP_LOGV(TAG, "Wake-up Nextion");
|
||||
this->ignore_is_setup_ = true;
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
this->send_command_("sleep=0");
|
||||
this->send_command_("dim=100");
|
||||
this->set_backlight_brightness(1.0);
|
||||
vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
|
||||
App.feed_wdt();
|
||||
char command[128];
|
||||
// Tells the Nextion the content length of the tft file and baud rate it will be sent at
|
||||
// Once the Nextion accepts the command it will wait until the file is successfully uploaded
|
||||
// If it fails for any reason a power cycle of the display will be needed
|
||||
sprintf(command, "whmi-wris %d,%" PRIu32 ",1", this->content_length_, baud_rate);
|
||||
sprintf(command, "whmi-wris %d,%" PRIu32 ",1", this->content_length_, this->parent_->get_baud_rate());
|
||||
|
||||
// Clear serial receive buffer
|
||||
ESP_LOGV(TAG, "Clear serial receive buffer");
|
||||
this->reset_(false);
|
||||
vTaskDelay(pdMS_TO_TICKS(250)); // NOLINT
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
uint8_t d;
|
||||
while (this->available()) {
|
||||
this->read_byte(&d);
|
||||
};
|
||||
|
||||
ESP_LOGV(TAG, "Send upload instruction: %s", command);
|
||||
ESP_LOGV(TAG, "Send update instruction: %s", command);
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
this->send_command_(command);
|
||||
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Changing baud rate from %" PRIu32 " to %" PRIu32 " bps", this->original_baud_rate_, baud_rate);
|
||||
this->parent_->set_baud_rate(baud_rate);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
|
||||
std::string response;
|
||||
ESP_LOGV(TAG, "Waiting for upgrade response");
|
||||
this->recv_ret_string_(response, 5000, true); // This can take some time to return
|
||||
|
||||
// The Nextion display will, if it's ready to accept data, send a 0x05 byte.
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu byte(s)",
|
||||
ESP_LOGD(TAG, "Upgrade response is [%s] - %zu bytes",
|
||||
format_hex_pretty(reinterpret_cast<const uint8_t *>(response.data()), response.size()).c_str(),
|
||||
response.length());
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
|
||||
if (response.find(0x05) != std::string::npos) {
|
||||
ESP_LOGV(TAG, "Preparation for TFT upload done");
|
||||
ESP_LOGV(TAG, "Preparation for tft update done");
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Preparation for TFT upload failed %d \"%s\"", response[0], response.c_str());
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
esp_http_client_close(http_client);
|
||||
esp_http_client_cleanup(http_client);
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
ESP_LOGE(TAG, "Preparation for tft update failed %d \"%s\"", response[0], response.c_str());
|
||||
return this->upload_end(false);
|
||||
}
|
||||
|
||||
ESP_LOGV(TAG, "Change the method to GET before starting the download");
|
||||
esp_err_t set_method_result = esp_http_client_set_method(http_client, HTTP_METHOD_GET);
|
||||
if (set_method_result != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set HTTP method to GET: %s", esp_err_to_name(set_method_result));
|
||||
return this->upload_end_(false);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Uploading TFT to Nextion:");
|
||||
ESP_LOGD(TAG, " URL: %s", this->tft_url_.c_str());
|
||||
ESP_LOGD(TAG, " File size: %" PRIu32 " bytes", this->content_length_);
|
||||
ESP_LOGD(TAG, " Free heap: %" PRIu32, esp_get_free_heap_size());
|
||||
|
||||
// Proceed with the content download as before
|
||||
ESP_LOGD(TAG, "Updating tft from \"%s\" with a file size of %d, Heap Size %" PRIu32, this->tft_url_.c_str(),
|
||||
content_length_, esp_get_free_heap_size());
|
||||
|
||||
ESP_LOGV(TAG, "Starting transfer by chunks loop");
|
||||
|
||||
uint32_t position = 0;
|
||||
while (this->content_length_ > 0) {
|
||||
int upload_result = upload_by_chunks_(http_client, position);
|
||||
if (upload_result < 0) {
|
||||
ESP_LOGE(TAG, "Error uploading TFT to Nextion!");
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
esp_http_client_close(http_client);
|
||||
esp_http_client_cleanup(http_client);
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(false);
|
||||
ESP_LOGVV(TAG, "Available heap: %" PRIu32, esp_get_free_heap_size());
|
||||
int result = 0;
|
||||
while (content_length_ > 0) {
|
||||
result = upload_range(this->tft_url_.c_str(), result);
|
||||
if (result < 0) {
|
||||
ESP_LOGE(TAG, "Error updating Nextion!");
|
||||
return this->upload_end(false);
|
||||
}
|
||||
App.feed_wdt();
|
||||
ESP_LOGV(TAG, "Free heap: %" PRIu32 ", Bytes left: %" PRIu32, esp_get_free_heap_size(), this->content_length_);
|
||||
ESP_LOGV(TAG, "Heap Size %" PRIu32 ", Bytes left %d", esp_get_free_heap_size(), content_length_);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Successfully uploaded TFT to Nextion!");
|
||||
ESP_LOGD(TAG, "Successfully updated Nextion!");
|
||||
|
||||
ESP_LOGD(TAG, "Close HTTP connection");
|
||||
esp_http_client_close(http_client);
|
||||
esp_http_client_cleanup(http_client);
|
||||
ESP_LOGV(TAG, "Connection closed");
|
||||
return this->upload_end_(true);
|
||||
return upload_end(true);
|
||||
}
|
||||
|
||||
bool Nextion::upload_end_(bool successful) {
|
||||
ESP_LOGD(TAG, "Nextion TFT upload finished: %s", YESNO(successful));
|
||||
bool Nextion::upload_end(bool successful) {
|
||||
this->is_updating_ = false;
|
||||
this->ignore_is_setup_ = false;
|
||||
|
||||
uint32_t baud_rate = this->parent_->get_baud_rate();
|
||||
if (baud_rate != this->original_baud_rate_) {
|
||||
ESP_LOGD(TAG, "Changing baud rate back from %" PRIu32 " to %" PRIu32 " bps", baud_rate, this->original_baud_rate_);
|
||||
this->parent_->set_baud_rate(this->original_baud_rate_);
|
||||
this->parent_->load_settings();
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Restarting Nextion");
|
||||
this->soft_reset();
|
||||
vTaskDelay(pdMS_TO_TICKS(1500)); // NOLINT
|
||||
if (successful) {
|
||||
ESP_LOGD(TAG, "Restarting ESPHome");
|
||||
delay(1500); // NOLINT
|
||||
arch_restart();
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Nextion TFT upload failed");
|
||||
esp_restart(); // NOLINT(readability-static-accessed-through-instance)
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
@@ -363,5 +321,5 @@ bool Nextion::upload_end_(bool successful) {
|
||||
} // namespace nextion
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ESP_IDF
|
||||
#endif // USE_NEXTION_TFT_UPLOAD
|
||||
#endif // USE_ESP_IDF
|
||||
|
||||
@@ -2,19 +2,14 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import nfc
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_ON_FINISHED_WRITE,
|
||||
CONF_ON_TAG_REMOVED,
|
||||
CONF_ON_TAG,
|
||||
CONF_TRIGGER_ID,
|
||||
)
|
||||
from esphome.const import CONF_ID, CONF_ON_TAG_REMOVED, CONF_ON_TAG, CONF_TRIGGER_ID
|
||||
|
||||
CODEOWNERS = ["@OttoWinter", "@jesserockz"]
|
||||
AUTO_LOAD = ["binary_sensor", "nfc"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_PN532_ID = "pn532_id"
|
||||
CONF_ON_FINISHED_WRITE = "on_finished_write"
|
||||
|
||||
pn532_ns = cg.esphome_ns.namespace("pn532")
|
||||
PN532 = pn532_ns.class_("PN532", cg.PollingComponent)
|
||||
|
||||
@@ -6,8 +6,6 @@ from esphome.components import nfc
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_IRQ_PIN,
|
||||
CONF_MESSAGE,
|
||||
CONF_ON_FINISHED_WRITE,
|
||||
CONF_ON_TAG_REMOVED,
|
||||
CONF_ON_TAG,
|
||||
CONF_TRIGGER_ID,
|
||||
@@ -20,6 +18,8 @@ CONF_EMULATION_MESSAGE = "emulation_message"
|
||||
CONF_EMULATION_OFF = "emulation_off"
|
||||
CONF_EMULATION_ON = "emulation_on"
|
||||
CONF_INCLUDE_ANDROID_APP_RECORD = "include_android_app_record"
|
||||
CONF_MESSAGE = "message"
|
||||
CONF_ON_FINISHED_WRITE = "on_finished_write"
|
||||
CONF_ON_EMULATED_TAG_SCAN = "on_emulated_tag_scan"
|
||||
CONF_PN7150_ID = "pn7150_id"
|
||||
CONF_POLLING_OFF = "polling_off"
|
||||
|
||||
@@ -6,8 +6,6 @@ from esphome.components import nfc
|
||||
from esphome.const import (
|
||||
CONF_ID,
|
||||
CONF_IRQ_PIN,
|
||||
CONF_MESSAGE,
|
||||
CONF_ON_FINISHED_WRITE,
|
||||
CONF_ON_TAG_REMOVED,
|
||||
CONF_ON_TAG,
|
||||
CONF_TRIGGER_ID,
|
||||
@@ -21,6 +19,8 @@ CONF_EMULATION_MESSAGE = "emulation_message"
|
||||
CONF_EMULATION_OFF = "emulation_off"
|
||||
CONF_EMULATION_ON = "emulation_on"
|
||||
CONF_INCLUDE_ANDROID_APP_RECORD = "include_android_app_record"
|
||||
CONF_MESSAGE = "message"
|
||||
CONF_ON_FINISHED_WRITE = "on_finished_write"
|
||||
CONF_ON_EMULATED_TAG_SCAN = "on_emulated_tag_scan"
|
||||
CONF_PN7160_ID = "pn7160_id"
|
||||
CONF_POLLING_OFF = "polling_off"
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.const import (
|
||||
CONF_ENABLE_ON_BOOT,
|
||||
CONF_ENABLE_TIME,
|
||||
CONF_ID,
|
||||
CONF_KEEP_ON_TIME,
|
||||
CONF_PIN,
|
||||
)
|
||||
from esphome.const import CONF_ENABLE_TIME, CONF_ID, CONF_KEEP_ON_TIME, CONF_PIN
|
||||
|
||||
CODEOWNERS = ["@esphome/core"]
|
||||
power_supply_ns = cg.esphome_ns.namespace("power_supply")
|
||||
PowerSupply = power_supply_ns.class_("PowerSupply", cg.Component)
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_ENABLE_ON_BOOT = "enable_on_boot"
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_ID): cv.declare_id(PowerSupply),
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# PULSE Filter
|
||||
|
||||
The PULSE filter filters noisy pulses by ensuring that the pulse is in a steady state for at least `filter_length` before allowing the state change to occur.
|
||||
It counts the pulse time from the rising edge that stayed high for at least `filter_length`, so noise before this won't be considered the start of a pulse.
|
||||
It then must see a low pulse that is at least `filter_length` long before a subsequent rising edge is considered a new pulse start.
|
||||
|
||||
It's operation should be the same as delayed_on_off from the Binary Sensor component.
|
||||
|
||||
There are three moving parts in the algorithm that are used to determine the state of the filter.
|
||||
|
||||
1. The time between interrupts, measured from the last interrupt, this is compared to filter_length to determine if the pulse has been in a steady state for long enough.
|
||||
2. A latch variable that is set true when a high pulse is long enough to be considered a valid pulse and is reset when a low pulse is long enough to allow for another pulse to begin.
|
||||
3. The previous and current state of the pin used to determine if the pulse is rising or falling.
|
||||
|
||||
## Ghost interrupts
|
||||
|
||||
Observations from the devices show that even though the interrupt should trigger on every rising or falling edge, sometimes interrupts show the same state twice in a row.
|
||||
The current theory is an interprets occurs, but then the pin changing back faster than the ISR can be called and read the value, meaning it sees the same state twice in a row.
|
||||
The algorithm interprets these when it sees them as two edges in a row, so will potentially reset a pulse if
|
||||
|
||||
## Pulse Filter Truth table
|
||||
|
||||
The following is all of the possible states of the filter along with the new inputs.
|
||||
It also shows a diagram of a possible series of interrupts that would cause the filter to enter that state.
|
||||
It then has the action that the filter should take and a description of what is happening.
|
||||
|
||||
Diagram legend
|
||||
|
||||
- `/` rising edge
|
||||
- `\` falling edge
|
||||
- `‾` high steady state of at least `filter_length`
|
||||
- `_` low steady state of at least `filter_length`
|
||||
- `¦` ghost interrupt
|
||||
|
||||
| Length | Latch | From | To | Diagram | Action | Description |
|
||||
| ------ | ----- | ---- | --- | ------- | ------------------ | ---------------------------------------------------------------------------------------------------- |
|
||||
| T | 1 | 0 | 0 | `‾\_¦ ` | Reset | `filter_length` low, reset the latch |
|
||||
| T | 1 | 0 | 1 | `‾\_/ ` | Reset, Rising Edge | `filter_length` low, reset the latch, rising edge could be a new pulse |
|
||||
| T | 1 | 1 | 0 | `‾\/‾\` | - | Already latched from a previous `filter_length` high |
|
||||
| T | 1 | 1 | 1 | `‾\/‾¦` | - | Already latched from a previous `filter_length` high |
|
||||
| T | 0 | 1 | 1 | `_/‾¦` | Set and Publish | `filter_length` high, set the latch and publish the pulse |
|
||||
| T | 0 | 1 | 0 | `_/‾\ ` | Set and Publish | `filter_length` high, set the latch and publish the pulse |
|
||||
| T | 0 | 0 | 1 | `_/\_/` | Rising Edge | Already unlatched from a previous `filter_length` low |
|
||||
| T | 0 | 0 | 0 | `_/\_¦` | - | Already unlatched from a previous `filter_length` low |
|
||||
| F | 1 | 0 | 0 | `‾\¦ ` | - | Low was not long enough to reset the latch |
|
||||
| F | 1 | 0 | 1 | `‾\/ ` | - | Low was not long enough to reset the latch |
|
||||
| F | 1 | 1 | 0 | `‾\/\ ` | - | Low was not long enough to reset the latch |
|
||||
| F | 1 | 1 | 1 | `‾¦ ` | - | Ghost of 0 length definitely was not long was not long enough to reset the latch |
|
||||
| F | 0 | 1 | 1 | `_/¦ ` | Rising Edge | High was not long enough to set the latch, but the second half of the ghost can be a new rising edge |
|
||||
| F | 0 | 1 | 0 | `_/\ ` | - | High was not long enough to set the latch |
|
||||
| F | 0 | 0 | 1 | `_/\/ ` | Rising Edge | High was not long enough to set the latch, but this may be a rising edge |
|
||||
| F | 0 | 0 | 0 | `_¦ ` | - | Ghost of 0 length definitely was not long was not long enough to set the latch |
|
||||
|
||||
## Startup
|
||||
|
||||
On startup the filter should not consider whatever state it is in as valid so it does not count a strange pulse.
|
||||
There are two possible starting configurations, either the pin is high or the pin is low.
|
||||
If the pin is high, the subsequent falling edge should not count as a pulse as we never saw the rising edge.
|
||||
Therefore we start in the latched state.
|
||||
If the pin is low, the subsequent rising edge can be counted as the first pulse.
|
||||
Therefore we start in the unlatched state.
|
||||
@@ -24,16 +24,11 @@ void PulseMeterSensor::setup() {
|
||||
if (this->filter_mode_ == FILTER_EDGE) {
|
||||
this->pin_->attach_interrupt(PulseMeterSensor::edge_intr, this, gpio::INTERRUPT_RISING_EDGE);
|
||||
} else if (this->filter_mode_ == FILTER_PULSE) {
|
||||
// Set the pin value to the current value to avoid a false edge
|
||||
this->pulse_state_.last_pin_val_ = this->isr_pin_.digital_read();
|
||||
this->pulse_state_.latched_ = this->pulse_state_.last_pin_val_;
|
||||
this->pin_->attach_interrupt(PulseMeterSensor::pulse_intr, this, gpio::INTERRUPT_ANY_EDGE);
|
||||
}
|
||||
}
|
||||
|
||||
void PulseMeterSensor::loop() {
|
||||
const uint32_t now = micros();
|
||||
|
||||
// Reset the count in get before we pass it back to the ISR as set
|
||||
this->get_->count_ = 0;
|
||||
|
||||
@@ -43,20 +38,6 @@ void PulseMeterSensor::loop() {
|
||||
this->set_ = this->get_;
|
||||
this->get_ = temp;
|
||||
|
||||
// If an edge was peeked, repay the debt
|
||||
if (this->peeked_edge_ && this->get_->count_ > 0) {
|
||||
this->peeked_edge_ = false;
|
||||
this->get_->count_--;
|
||||
}
|
||||
|
||||
// If there is an unprocessed edge, and filter_us_ has passed since, count this edge early
|
||||
if (this->get_->last_rising_edge_us_ != this->get_->last_detected_edge_us_ &&
|
||||
now - this->get_->last_rising_edge_us_ >= this->filter_us_) {
|
||||
this->peeked_edge_ = true;
|
||||
this->get_->last_detected_edge_us_ = this->get_->last_rising_edge_us_;
|
||||
this->get_->count_++;
|
||||
}
|
||||
|
||||
// Check if we detected a pulse this loop
|
||||
if (this->get_->count_ > 0) {
|
||||
// Keep a running total of pulses if a total sensor is configured
|
||||
@@ -83,6 +64,7 @@ void PulseMeterSensor::loop() {
|
||||
}
|
||||
// No detected edges this loop
|
||||
else {
|
||||
const uint32_t now = micros();
|
||||
const uint32_t time_since_valid_edge_us = now - this->last_processed_edge_us_;
|
||||
|
||||
switch (this->meter_state_) {
|
||||
@@ -120,14 +102,11 @@ void IRAM_ATTR PulseMeterSensor::edge_intr(PulseMeterSensor *sensor) {
|
||||
// This is an interrupt handler - we can't call any virtual method from this method
|
||||
// Get the current time before we do anything else so the measurements are consistent
|
||||
const uint32_t now = micros();
|
||||
auto &state = sensor->edge_state_;
|
||||
auto &set = *sensor->set_;
|
||||
|
||||
if ((now - state.last_sent_edge_us_) >= sensor->filter_us_) {
|
||||
state.last_sent_edge_us_ = now;
|
||||
set.last_detected_edge_us_ = now;
|
||||
set.last_rising_edge_us_ = now;
|
||||
set.count_++;
|
||||
if ((now - sensor->last_edge_candidate_us_) >= sensor->filter_us_) {
|
||||
sensor->last_edge_candidate_us_ = now;
|
||||
sensor->set_->last_detected_edge_us_ = now;
|
||||
sensor->set_->count_++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,27 +115,33 @@ void IRAM_ATTR PulseMeterSensor::pulse_intr(PulseMeterSensor *sensor) {
|
||||
// Get the current time before we do anything else so the measurements are consistent
|
||||
const uint32_t now = micros();
|
||||
const bool pin_val = sensor->isr_pin_.digital_read();
|
||||
auto &state = sensor->pulse_state_;
|
||||
auto &set = *sensor->set_;
|
||||
|
||||
// Filter length has passed since the last interrupt
|
||||
const bool length = now - state.last_intr_ >= sensor->filter_us_;
|
||||
// A pulse occurred faster than we can detect
|
||||
if (sensor->last_pin_val_ == pin_val) {
|
||||
// If we haven't reached the filter length yet we need to reset our last_intr_ to now
|
||||
// otherwise we can consider this noise as the "pulse" was certainly less than filter_us_
|
||||
if (now - sensor->last_intr_ < sensor->filter_us_) {
|
||||
sensor->last_intr_ = now;
|
||||
}
|
||||
} else {
|
||||
// Check if the last interrupt was long enough in the past
|
||||
if (now - sensor->last_intr_ > sensor->filter_us_) {
|
||||
// High pulse of filter length now falling (therefore last_intr_ was the rising edge)
|
||||
if (!sensor->in_pulse_ && sensor->last_pin_val_) {
|
||||
sensor->last_edge_candidate_us_ = sensor->last_intr_;
|
||||
sensor->in_pulse_ = true;
|
||||
}
|
||||
// Low pulse of filter length now rising (therefore last_intr_ was the falling edge)
|
||||
else if (sensor->in_pulse_ && !sensor->last_pin_val_) {
|
||||
sensor->set_->last_detected_edge_us_ = sensor->last_edge_candidate_us_;
|
||||
sensor->set_->count_++;
|
||||
sensor->in_pulse_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (length && state.latched_ && !state.last_pin_val_) { // Long enough low edge
|
||||
state.latched_ = false;
|
||||
} else if (length && !state.latched_ && state.last_pin_val_) { // Long enough high edge
|
||||
state.latched_ = true;
|
||||
set.last_detected_edge_us_ = state.last_intr_;
|
||||
set.count_++;
|
||||
sensor->last_intr_ = now;
|
||||
sensor->last_pin_val_ = pin_val;
|
||||
}
|
||||
|
||||
// Due to order of operations this includes
|
||||
// length && latched && rising (just reset from a long low edge)
|
||||
// !latched && (rising || high) (noise on the line resetting the potential rising edge)
|
||||
set.last_rising_edge_us_ = !state.latched_ && pin_val ? now : set.last_detected_edge_us_;
|
||||
|
||||
state.last_intr_ = now;
|
||||
state.last_pin_val_ = pin_val;
|
||||
}
|
||||
|
||||
} // namespace pulse_meter
|
||||
|
||||
@@ -43,7 +43,6 @@ class PulseMeterSensor : public sensor::Sensor, public Component {
|
||||
// Variables used in the loop
|
||||
enum class MeterState { INITIAL, RUNNING, TIMED_OUT };
|
||||
MeterState meter_state_ = MeterState::INITIAL;
|
||||
bool peeked_edge_ = false;
|
||||
uint32_t total_pulses_ = 0;
|
||||
uint32_t last_processed_edge_us_ = 0;
|
||||
|
||||
@@ -54,7 +53,6 @@ class PulseMeterSensor : public sensor::Sensor, public Component {
|
||||
// (except for resetting the values)
|
||||
struct State {
|
||||
uint32_t last_detected_edge_us_ = 0;
|
||||
uint32_t last_rising_edge_us_ = 0;
|
||||
uint32_t count_ = 0;
|
||||
};
|
||||
State state_[2];
|
||||
@@ -63,20 +61,10 @@ class PulseMeterSensor : public sensor::Sensor, public Component {
|
||||
|
||||
// Only use these variables in the ISR
|
||||
ISRInternalGPIOPin isr_pin_;
|
||||
|
||||
/// Filter state for edge mode
|
||||
struct EdgeState {
|
||||
uint32_t last_sent_edge_us_ = 0;
|
||||
};
|
||||
EdgeState edge_state_{};
|
||||
|
||||
/// Filter state for pulse mode
|
||||
struct PulseState {
|
||||
uint32_t last_intr_ = 0;
|
||||
bool latched_ = false;
|
||||
bool last_pin_val_ = false;
|
||||
};
|
||||
PulseState pulse_state_{};
|
||||
uint32_t last_edge_candidate_us_ = 0;
|
||||
uint32_t last_intr_ = 0;
|
||||
bool in_pulse_ = false;
|
||||
bool last_pin_val_ = false;
|
||||
};
|
||||
|
||||
} // namespace pulse_meter
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#include "qmc5883l.h"
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include <cmath>
|
||||
@@ -60,10 +59,6 @@ void QMC5883LComponent::setup() {
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this->get_update_interval() < App.get_loop_interval()) {
|
||||
high_freq_.start();
|
||||
}
|
||||
}
|
||||
void QMC5883LComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "QMC5883L:");
|
||||
|
||||
@@ -56,7 +56,6 @@ class QMC5883LComponent : public PollingComponent, public i2c::I2CDevice {
|
||||
COMMUNICATION_FAILED,
|
||||
} error_code_;
|
||||
bool read_byte_16_(uint8_t a_register, uint16_t *data);
|
||||
HighFrequencyLoopRequester high_freq_;
|
||||
};
|
||||
|
||||
} // namespace qmc5883l
|
||||
|
||||
@@ -6,7 +6,6 @@ from esphome.const import (
|
||||
CONF_FIELD_STRENGTH_X,
|
||||
CONF_FIELD_STRENGTH_Y,
|
||||
CONF_FIELD_STRENGTH_Z,
|
||||
CONF_HEADING,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_ID,
|
||||
CONF_OVERSAMPLING,
|
||||
@@ -25,6 +24,8 @@ DEPENDENCIES = ["i2c"]
|
||||
|
||||
qmc5883l_ns = cg.esphome_ns.namespace("qmc5883l")
|
||||
|
||||
CONF_HEADING = "heading"
|
||||
|
||||
QMC5883LComponent = qmc5883l_ns.class_(
|
||||
"QMC5883LComponent", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
@@ -108,18 +108,18 @@ void RemoteReceiverBase::register_dumper(RemoteReceiverDumperBase *dumper) {
|
||||
|
||||
void RemoteReceiverBase::call_listeners_() {
|
||||
for (auto *listener : this->listeners_)
|
||||
listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
|
||||
listener->on_receive(RemoteReceiveData(this->temp_, this->tolerance_));
|
||||
}
|
||||
|
||||
void RemoteReceiverBase::call_dumpers_() {
|
||||
bool success = false;
|
||||
for (auto *dumper : this->dumpers_) {
|
||||
if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_)))
|
||||
if (dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_)))
|
||||
success = true;
|
||||
}
|
||||
if (!success) {
|
||||
for (auto *dumper : this->secondary_dumpers_)
|
||||
dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_, this->tolerance_mode_));
|
||||
dumper->dump(RemoteReceiveData(this->temp_, this->tolerance_));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
namespace esphome {
|
||||
namespace remote_base {
|
||||
|
||||
enum ToleranceMode : uint8_t {
|
||||
TOLERANCE_MODE_PERCENTAGE = 0,
|
||||
TOLERANCE_MODE_TIME = 1,
|
||||
};
|
||||
|
||||
using RawTimings = std::vector<int32_t>;
|
||||
|
||||
class RemoteTransmitData {
|
||||
@@ -47,8 +42,8 @@ class RemoteTransmitData {
|
||||
|
||||
class RemoteReceiveData {
|
||||
public:
|
||||
explicit RemoteReceiveData(const RawTimings &data, uint32_t tolerance, ToleranceMode tolerance_mode)
|
||||
: data_(data), index_(0), tolerance_(tolerance), tolerance_mode_(tolerance_mode) {}
|
||||
explicit RemoteReceiveData(const RawTimings &data, uint8_t tolerance)
|
||||
: data_(data), index_(0), tolerance_(tolerance) {}
|
||||
|
||||
const RawTimings &get_raw_data() const { return this->data_; }
|
||||
uint32_t get_index() const { return index_; }
|
||||
@@ -70,35 +65,13 @@ class RemoteReceiveData {
|
||||
void advance(uint32_t amount = 1) { this->index_ += amount; }
|
||||
void reset() { this->index_ = 0; }
|
||||
|
||||
void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) {
|
||||
this->tolerance_ = tolerance;
|
||||
this->tolerance_mode_ = tolerance_mode;
|
||||
}
|
||||
uint32_t get_tolerance() { return tolerance_; }
|
||||
ToleranceMode get_tolerance_mode() { return this->tolerance_mode_; }
|
||||
|
||||
protected:
|
||||
int32_t lower_bound_(uint32_t length) const {
|
||||
if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) {
|
||||
return int32_t(length - this->tolerance_);
|
||||
} else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) {
|
||||
return int32_t(100 - this->tolerance_) * length / 100U;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int32_t upper_bound_(uint32_t length) const {
|
||||
if (this->tolerance_mode_ == TOLERANCE_MODE_TIME) {
|
||||
return int32_t(length + this->tolerance_);
|
||||
} else if (this->tolerance_mode_ == TOLERANCE_MODE_PERCENTAGE) {
|
||||
return int32_t(100 + this->tolerance_) * length / 100U;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int32_t lower_bound_(uint32_t length) const { return int32_t(100 - this->tolerance_) * length / 100U; }
|
||||
int32_t upper_bound_(uint32_t length) const { return int32_t(100 + this->tolerance_) * length / 100U; }
|
||||
|
||||
const RawTimings &data_;
|
||||
uint32_t index_;
|
||||
uint32_t tolerance_;
|
||||
ToleranceMode tolerance_mode_;
|
||||
uint8_t tolerance_;
|
||||
};
|
||||
|
||||
class RemoteComponentBase {
|
||||
@@ -189,10 +162,7 @@ class RemoteReceiverBase : public RemoteComponentBase {
|
||||
RemoteReceiverBase(InternalGPIOPin *pin) : RemoteComponentBase(pin) {}
|
||||
void register_listener(RemoteReceiverListener *listener) { this->listeners_.push_back(listener); }
|
||||
void register_dumper(RemoteReceiverDumperBase *dumper);
|
||||
void set_tolerance(uint32_t tolerance, ToleranceMode tolerance_mode) {
|
||||
this->tolerance_ = tolerance;
|
||||
this->tolerance_mode_ = tolerance_mode;
|
||||
}
|
||||
void set_tolerance(uint8_t tolerance) { tolerance_ = tolerance; }
|
||||
|
||||
protected:
|
||||
void call_listeners_();
|
||||
@@ -206,8 +176,7 @@ class RemoteReceiverBase : public RemoteComponentBase {
|
||||
std::vector<RemoteReceiverDumperBase *> dumpers_;
|
||||
std::vector<RemoteReceiverDumperBase *> secondary_dumpers_;
|
||||
RawTimings temp_;
|
||||
uint32_t tolerance_{25};
|
||||
ToleranceMode tolerance_mode_{TOLERANCE_MODE_PERCENTAGE};
|
||||
uint8_t tolerance_;
|
||||
};
|
||||
|
||||
class RemoteReceiverBinarySensorBase : public binary_sensor::BinarySensorInitiallyOff,
|
||||
|
||||
@@ -10,69 +10,17 @@ from esphome.const import (
|
||||
CONF_IDLE,
|
||||
CONF_PIN,
|
||||
CONF_TOLERANCE,
|
||||
CONF_TYPE,
|
||||
CONF_MEMORY_BLOCKS,
|
||||
CONF_RMT_CHANNEL,
|
||||
CONF_VALUE,
|
||||
)
|
||||
from esphome.core import CORE, TimePeriod
|
||||
|
||||
CONF_CLOCK_DIVIDER = "clock_divider"
|
||||
|
||||
AUTO_LOAD = ["remote_base"]
|
||||
remote_receiver_ns = cg.esphome_ns.namespace("remote_receiver")
|
||||
remote_base_ns = cg.esphome_ns.namespace("remote_base")
|
||||
|
||||
ToleranceMode = remote_base_ns.enum("ToleranceMode")
|
||||
|
||||
TYPE_PERCENTAGE = "percentage"
|
||||
TYPE_TIME = "time"
|
||||
|
||||
TOLERANCE_MODE = {
|
||||
TYPE_PERCENTAGE: ToleranceMode.TOLERANCE_MODE_PERCENTAGE,
|
||||
TYPE_TIME: ToleranceMode.TOLERANCE_MODE_TIME,
|
||||
}
|
||||
|
||||
TOLERANCE_SCHEMA = cv.typed_schema(
|
||||
{
|
||||
TYPE_PERCENTAGE: cv.Schema(
|
||||
{cv.Required(CONF_VALUE): cv.All(cv.percentage_int, cv.uint32_t)}
|
||||
),
|
||||
TYPE_TIME: cv.Schema(
|
||||
{
|
||||
cv.Required(CONF_VALUE): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
lower=True,
|
||||
enum=TOLERANCE_MODE,
|
||||
)
|
||||
|
||||
RemoteReceiverComponent = remote_receiver_ns.class_(
|
||||
"RemoteReceiverComponent", remote_base.RemoteReceiverBase, cg.Component
|
||||
)
|
||||
|
||||
|
||||
def validate_tolerance(value):
|
||||
if isinstance(value, dict):
|
||||
return TOLERANCE_SCHEMA(value)
|
||||
|
||||
if "%" in str(value):
|
||||
type_ = TYPE_PERCENTAGE
|
||||
else:
|
||||
type_ = TYPE_TIME
|
||||
|
||||
return TOLERANCE_SCHEMA(
|
||||
{
|
||||
CONF_VALUE: value,
|
||||
CONF_TYPE: type_,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
MULTI_CONF = True
|
||||
CONFIG_SCHEMA = remote_base.validate_triggers(
|
||||
cv.Schema(
|
||||
@@ -80,7 +28,9 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
||||
cv.GenerateID(): cv.declare_id(RemoteReceiverComponent),
|
||||
cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema),
|
||||
cv.Optional(CONF_DUMP, default=[]): remote_base.validate_dumpers,
|
||||
cv.Optional(CONF_TOLERANCE, default="25%"): validate_tolerance,
|
||||
cv.Optional(CONF_TOLERANCE, default=25): cv.All(
|
||||
cv.percentage_int, cv.Range(min=0)
|
||||
),
|
||||
cv.SplitDefault(
|
||||
CONF_BUFFER_SIZE,
|
||||
esp32="10000b",
|
||||
@@ -90,15 +40,11 @@ CONFIG_SCHEMA = remote_base.validate_triggers(
|
||||
): cv.validate_bytes,
|
||||
cv.Optional(CONF_FILTER, default="50us"): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||
),
|
||||
cv.SplitDefault(CONF_CLOCK_DIVIDER, esp32=80): cv.All(
|
||||
cv.only_on_esp32, cv.Range(min=1, max=255)
|
||||
),
|
||||
cv.Optional(CONF_IDLE, default="10ms"): cv.All(
|
||||
cv.positive_time_period_microseconds,
|
||||
cv.Range(max=TimePeriod(microseconds=4294967295)),
|
||||
cv.Range(max=TimePeriod(microseconds=255)),
|
||||
),
|
||||
cv.Optional(
|
||||
CONF_IDLE, default="10ms"
|
||||
): cv.positive_time_period_microseconds,
|
||||
cv.Optional(CONF_MEMORY_BLOCKS, default=3): cv.Range(min=1, max=8),
|
||||
cv.Optional(CONF_RMT_CHANNEL): esp32_rmt.validate_rmt_channel(tx=False),
|
||||
}
|
||||
@@ -115,7 +61,6 @@ async def to_code(config):
|
||||
)
|
||||
else:
|
||||
var = cg.new_Pvariable(config[CONF_ID], pin, config[CONF_MEMORY_BLOCKS])
|
||||
cg.add(var.set_clock_divider(config[CONF_CLOCK_DIVIDER]))
|
||||
else:
|
||||
var = cg.new_Pvariable(config[CONF_ID], pin)
|
||||
|
||||
@@ -128,11 +73,7 @@ async def to_code(config):
|
||||
cg.add(var.register_listener(trigger))
|
||||
await cg.register_component(var, config)
|
||||
|
||||
cg.add(
|
||||
var.set_tolerance(
|
||||
config[CONF_TOLERANCE][CONF_VALUE], config[CONF_TOLERANCE][CONF_TYPE]
|
||||
)
|
||||
)
|
||||
cg.add(var.set_tolerance(config[CONF_TOLERANCE]))
|
||||
cg.add(var.set_buffer_size(config[CONF_BUFFER_SIZE]))
|
||||
cg.add(var.set_filter_us(config[CONF_FILTER]))
|
||||
cg.add(var.set_idle_us(config[CONF_IDLE]))
|
||||
|
||||
@@ -22,7 +22,7 @@ struct RemoteReceiverComponentStore {
|
||||
uint32_t buffer_read_at{0};
|
||||
bool overflow{false};
|
||||
uint32_t buffer_size{1000};
|
||||
uint32_t filter_us{10};
|
||||
uint8_t filter_us{10};
|
||||
ISRInternalGPIOPin pin;
|
||||
};
|
||||
#endif
|
||||
@@ -50,7 +50,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase,
|
||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||
|
||||
void set_buffer_size(uint32_t buffer_size) { this->buffer_size_ = buffer_size; }
|
||||
void set_filter_us(uint32_t filter_us) { this->filter_us_ = filter_us; }
|
||||
void set_filter_us(uint8_t filter_us) { this->filter_us_ = filter_us; }
|
||||
void set_idle_us(uint32_t idle_us) { this->idle_us_ = idle_us; }
|
||||
|
||||
protected:
|
||||
@@ -58,7 +58,6 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase,
|
||||
void decode_rmt_(rmt_item32_t *item, size_t len);
|
||||
RingbufHandle_t ringbuf_;
|
||||
esp_err_t error_code_{ESP_OK};
|
||||
std::string error_string_{""};
|
||||
#endif
|
||||
|
||||
#if defined(USE_ESP8266) || defined(USE_LIBRETINY)
|
||||
@@ -67,7 +66,7 @@ class RemoteReceiverComponent : public remote_base::RemoteReceiverBase,
|
||||
#endif
|
||||
|
||||
uint32_t buffer_size_{};
|
||||
uint32_t filter_us_{10};
|
||||
uint8_t filter_us_{10};
|
||||
uint32_t idle_us_{10000};
|
||||
};
|
||||
|
||||
|
||||
@@ -20,16 +20,13 @@ void RemoteReceiverComponent::setup() {
|
||||
rmt.rx_config.filter_en = false;
|
||||
} else {
|
||||
rmt.rx_config.filter_en = true;
|
||||
rmt.rx_config.filter_ticks_thresh = static_cast<uint8_t>(
|
||||
std::min(this->from_microseconds_(this->filter_us_) * this->clock_divider_, (uint32_t) 255));
|
||||
rmt.rx_config.filter_ticks_thresh = this->from_microseconds_(this->filter_us_);
|
||||
}
|
||||
rmt.rx_config.idle_threshold =
|
||||
static_cast<uint16_t>(std::min(this->from_microseconds_(this->idle_us_), (uint32_t) 65535));
|
||||
rmt.rx_config.idle_threshold = this->from_microseconds_(this->idle_us_);
|
||||
|
||||
esp_err_t error = rmt_config(&rmt);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
this->error_string_ = "in rmt_config";
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -37,25 +34,18 @@ void RemoteReceiverComponent::setup() {
|
||||
error = rmt_driver_install(this->channel_, this->buffer_size_, 0);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
if (error == ESP_ERR_INVALID_STATE) {
|
||||
this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_);
|
||||
} else {
|
||||
this->error_string_ = "in rmt_driver_install";
|
||||
}
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
error = rmt_get_ringbuf_handle(this->channel_, &this->ringbuf_);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
this->error_string_ = "in rmt_get_ringbuf_handle";
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
error = rmt_rx_start(this->channel_, true);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
this->error_string_ = "in rmt_rx_start";
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -70,13 +60,11 @@ void RemoteReceiverComponent::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, " Channel: %d", this->channel_);
|
||||
ESP_LOGCONFIG(TAG, " RMT memory blocks: %d", this->mem_block_num_);
|
||||
ESP_LOGCONFIG(TAG, " Clock divider: %u", this->clock_divider_);
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %" PRIu32 "%s", this->tolerance_,
|
||||
(this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%");
|
||||
ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %" PRIu32 " us", this->filter_us_);
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_);
|
||||
ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_);
|
||||
ESP_LOGCONFIG(TAG, " Signal is done after %" PRIu32 " us of no changes", this->idle_us_);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_),
|
||||
this->error_string_.c_str());
|
||||
ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +88,6 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) {
|
||||
this->temp_.clear();
|
||||
int32_t multiplier = this->pin_->is_inverted() ? -1 : 1;
|
||||
size_t item_count = len / sizeof(rmt_item32_t);
|
||||
uint32_t filter_ticks = this->from_microseconds_(this->filter_us_);
|
||||
|
||||
ESP_LOGVV(TAG, "START:");
|
||||
for (size_t i = 0; i < item_count; i++) {
|
||||
@@ -125,7 +112,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) {
|
||||
for (size_t i = 0; i < item_count; i++) {
|
||||
if (item[i].duration0 == 0u) {
|
||||
// Do nothing
|
||||
} else if ((bool(item[i].level0) == prev_level) || (item[i].duration0 < filter_ticks)) {
|
||||
} else if (bool(item[i].level0) == prev_level) {
|
||||
prev_length += item[i].duration0;
|
||||
} else {
|
||||
if (prev_length > 0) {
|
||||
@@ -141,7 +128,7 @@ void RemoteReceiverComponent::decode_rmt_(rmt_item32_t *item, size_t len) {
|
||||
|
||||
if (item[i].duration1 == 0u) {
|
||||
// Do nothing
|
||||
} else if ((bool(item[i].level1) == prev_level) || (item[i].duration1 < filter_ticks)) {
|
||||
} else if (bool(item[i].level1) == prev_level) {
|
||||
prev_length += item[i].duration1;
|
||||
} else {
|
||||
if (prev_length > 0) {
|
||||
|
||||
@@ -64,8 +64,7 @@ void RemoteReceiverComponent::dump_config() {
|
||||
"invert the signal using 'inverted: True' in the pin schema!");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_);
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_,
|
||||
(this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%");
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_);
|
||||
ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_);
|
||||
ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_);
|
||||
}
|
||||
|
||||
@@ -64,8 +64,7 @@ void RemoteReceiverComponent::dump_config() {
|
||||
"invert the signal using 'inverted: True' in the pin schema!");
|
||||
}
|
||||
ESP_LOGCONFIG(TAG, " Buffer Size: %u", this->buffer_size_);
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %u%s", this->tolerance_,
|
||||
(this->tolerance_mode_ == remote_base::TOLERANCE_MODE_TIME) ? " us" : "%");
|
||||
ESP_LOGCONFIG(TAG, " Tolerance: %u%%", this->tolerance_);
|
||||
ESP_LOGCONFIG(TAG, " Filter out pulses shorter than: %u us", this->filter_us_);
|
||||
ESP_LOGCONFIG(TAG, " Signal is done after %u us of no changes", this->idle_us_);
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
|
||||
bool initialized_{false};
|
||||
std::vector<rmt_item32_t> rmt_temp_;
|
||||
esp_err_t error_code_{ESP_OK};
|
||||
std::string error_string_{""};
|
||||
bool inverted_{false};
|
||||
#endif
|
||||
uint8_t carrier_duty_percent_;
|
||||
|
||||
@@ -23,8 +23,7 @@ void RemoteTransmitterComponent::dump_config() {
|
||||
}
|
||||
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Configuring RMT driver failed: %s (%s)", esp_err_to_name(this->error_code_),
|
||||
this->error_string_.c_str());
|
||||
ESP_LOGE(TAG, "Configuring RMT driver failed: %s", esp_err_to_name(this->error_code_));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,7 +56,6 @@ void RemoteTransmitterComponent::configure_rmt_() {
|
||||
esp_err_t error = rmt_config(&c);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
this->error_string_ = "in rmt_config";
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
@@ -66,11 +64,6 @@ void RemoteTransmitterComponent::configure_rmt_() {
|
||||
error = rmt_driver_install(this->channel_, 0, 0);
|
||||
if (error != ESP_OK) {
|
||||
this->error_code_ = error;
|
||||
if (error == ESP_ERR_INVALID_STATE) {
|
||||
this->error_string_ = str_sprintf("RMT channel %i is already in use by another component", this->channel_);
|
||||
} else {
|
||||
this->error_string_ = "in rmt_driver_install";
|
||||
}
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor, resistance_sampler
|
||||
from esphome.const import (
|
||||
CONF_REFERENCE_VOLTAGE,
|
||||
CONF_SENSOR,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
UNIT_OHM,
|
||||
@@ -19,6 +18,7 @@ ResistanceSensor = resistance_ns.class_(
|
||||
resistance_sampler.ResistanceSampler,
|
||||
)
|
||||
|
||||
CONF_REFERENCE_VOLTAGE = "reference_voltage"
|
||||
CONF_CONFIGURATION = "configuration"
|
||||
CONF_RESISTOR = "resistor"
|
||||
|
||||
|
||||
@@ -3,13 +3,11 @@ import esphome.config_validation as cv
|
||||
from esphome import pins
|
||||
from esphome.components import display
|
||||
from esphome.const import (
|
||||
CONF_HSYNC_PIN,
|
||||
CONF_RESET_PIN,
|
||||
CONF_DATA_PINS,
|
||||
CONF_ID,
|
||||
CONF_IGNORE_STRAPPING_WARNING,
|
||||
CONF_DIMENSIONS,
|
||||
CONF_VSYNC_PIN,
|
||||
CONF_WIDTH,
|
||||
CONF_HEIGHT,
|
||||
CONF_LAMBDA,
|
||||
@@ -31,6 +29,8 @@ DEPENDENCIES = ["esp32"]
|
||||
|
||||
CONF_DE_PIN = "de_pin"
|
||||
CONF_PCLK_PIN = "pclk_pin"
|
||||
CONF_HSYNC_PIN = "hsync_pin"
|
||||
CONF_VSYNC_PIN = "vsync_pin"
|
||||
|
||||
CONF_HSYNC_FRONT_PORCH = "hsync_front_porch"
|
||||
CONF_HSYNC_PULSE_WIDTH = "hsync_pulse_width"
|
||||
|
||||
@@ -8,7 +8,6 @@ from esphome.const import (
|
||||
CONF_HUMIDITY,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_CO2,
|
||||
CONF_TEMPERATURE_OFFSET,
|
||||
CONF_UPDATE_INTERVAL,
|
||||
CONF_VALUE,
|
||||
DEVICE_CLASS_CARBON_DIOXIDE,
|
||||
@@ -37,6 +36,7 @@ ForceRecalibrationWithReference = scd30_ns.class_(
|
||||
CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration"
|
||||
CONF_ALTITUDE_COMPENSATION = "altitude_compensation"
|
||||
CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation"
|
||||
CONF_TEMPERATURE_OFFSET = "temperature_offset"
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
|
||||
@@ -10,7 +10,6 @@ from esphome.const import (
|
||||
CONF_CO2,
|
||||
CONF_HUMIDITY,
|
||||
CONF_TEMPERATURE,
|
||||
CONF_TEMPERATURE_OFFSET,
|
||||
CONF_VALUE,
|
||||
DEVICE_CLASS_CARBON_DIOXIDE,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
@@ -53,6 +52,7 @@ CONF_AMBIENT_PRESSURE_COMPENSATION = "ambient_pressure_compensation"
|
||||
CONF_AMBIENT_PRESSURE_COMPENSATION_SOURCE = "ambient_pressure_compensation_source"
|
||||
CONF_AUTOMATIC_SELF_CALIBRATION = "automatic_self_calibration"
|
||||
CONF_MEASUREMENT_MODE = "measurement_mode"
|
||||
CONF_TEMPERATURE_OFFSET = "temperature_offset"
|
||||
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user