mirror of https://github.com/esphome/esphome.git
Merge branch 'dev' into apds9306
This commit is contained in:
commit
2bd7f1a9dd
|
@ -34,6 +34,16 @@ runs:
|
|||
echo $l >> $GITHUB_OUTPUT
|
||||
done
|
||||
|
||||
# set cache-to only if dev branch
|
||||
- id: cache-to
|
||||
shell: bash
|
||||
run: |-
|
||||
if [[ "${{ github.ref }}" == "refs/heads/dev" ]]; then
|
||||
echo "value=type=gha,mode=max" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "value=" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build and push to ghcr by digest
|
||||
id: build-ghcr
|
||||
uses: docker/build-push-action@v5.3.0
|
||||
|
@ -43,7 +53,7 @@ runs:
|
|||
platforms: ${{ inputs.platform }}
|
||||
target: ${{ inputs.target }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
cache-to: ${{ steps.cache-to.outputs.value }}
|
||||
build-args: |
|
||||
BASEIMGTYPE=${{ inputs.baseimg }}
|
||||
BUILD_VERSION=${{ inputs.version }}
|
||||
|
@ -66,7 +76,7 @@ runs:
|
|||
platforms: ${{ inputs.platform }}
|
||||
target: ${{ inputs.target }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
cache-to: ${{ steps.cache-to.outputs.value }}
|
||||
build-args: |
|
||||
BASEIMGTYPE=${{ inputs.baseimg }}
|
||||
BUILD_VERSION=${{ inputs.version }}
|
||||
|
|
|
@ -364,12 +364,20 @@ jobs:
|
|||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
cache-key: ${{ needs.common.outputs.cache-key }}
|
||||
|
||||
- name: Cache platformio
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
uses: actions/cache@v4.0.2
|
||||
with:
|
||||
path: ~/.platformio
|
||||
# yamllint disable-line rule:line-length
|
||||
key: platformio-${{ matrix.pio_cache_key }}-${{ hashFiles('platformio.ini') }}
|
||||
key: platformio-${{ matrix.pio_cache_key }}
|
||||
|
||||
- name: Cache platformio
|
||||
if: github.ref != 'refs/heads/dev'
|
||||
uses: actions/cache/restore@v4.0.2
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: platformio-${{ matrix.pio_cache_key }}
|
||||
|
||||
- name: Install clang-tidy
|
||||
run: sudo apt-get install clang-tidy-14
|
||||
|
|
|
@ -40,3 +40,10 @@ repos:
|
|||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c, c++]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pylint
|
||||
name: pylint
|
||||
entry: pylint
|
||||
language: system
|
||||
types: [python]
|
||||
|
|
|
@ -136,6 +136,7 @@ esphome/components/fs3000/* @kahrendt
|
|||
esphome/components/ft5x06/* @clydebarrow
|
||||
esphome/components/ft63x6/* @gpambrozio
|
||||
esphome/components/gcja5/* @gcormier
|
||||
esphome/components/gdk101/* @Szewcson
|
||||
esphome/components/globals/* @esphome/core
|
||||
esphome/components/gp8403/* @jesserockz
|
||||
esphome/components/gpio/* @esphome/core
|
||||
|
|
|
@ -65,7 +65,7 @@ def choose_prompt(options, purpose: str = None):
|
|||
f'Found multiple options{f" for {purpose}" if purpose else ""}, please choose one:'
|
||||
)
|
||||
for i, (desc, _) in enumerate(options):
|
||||
safe_print(f" [{i+1}] {desc}")
|
||||
safe_print(f" [{i + 1}] {desc}")
|
||||
|
||||
while True:
|
||||
opt = input("(number): ")
|
||||
|
|
|
@ -157,7 +157,7 @@ async def to_code(config):
|
|||
pixels = list(frame.getdata())
|
||||
if len(pixels) != height * width:
|
||||
raise core.EsphomeError(
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
|
||||
)
|
||||
for pix, a in pixels:
|
||||
if transparent:
|
||||
|
@ -180,7 +180,7 @@ async def to_code(config):
|
|||
pixels = list(frame.getdata())
|
||||
if len(pixels) != height * width:
|
||||
raise core.EsphomeError(
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
|
||||
)
|
||||
for pix in pixels:
|
||||
data[pos] = pix[0]
|
||||
|
@ -203,7 +203,7 @@ async def to_code(config):
|
|||
pixels = list(frame.getdata())
|
||||
if len(pixels) != height * width:
|
||||
raise core.EsphomeError(
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
|
||||
)
|
||||
for r, g, b, a in pixels:
|
||||
if transparent:
|
||||
|
@ -232,7 +232,7 @@ async def to_code(config):
|
|||
pixels = list(frame.getdata())
|
||||
if len(pixels) != height * width:
|
||||
raise core.EsphomeError(
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height*width})"
|
||||
f"Unexpected number of pixels in {path} frame {frameIndex}: ({len(pixels)} != {height * width})"
|
||||
)
|
||||
for r, g, b, a in pixels:
|
||||
R = r >> 3
|
||||
|
|
|
@ -1147,6 +1147,9 @@ message MediaPlayerCommandRequest {
|
|||
|
||||
bool has_media_url = 6;
|
||||
string media_url = 7;
|
||||
|
||||
bool has_announcement = 8;
|
||||
bool announcement = 9;
|
||||
}
|
||||
|
||||
// ==================== BLUETOOTH ====================
|
||||
|
|
|
@ -1002,7 +1002,11 @@ bool APIConnection::send_media_player_state(media_player::MediaPlayer *media_pla
|
|||
|
||||
MediaPlayerStateResponse resp{};
|
||||
resp.key = media_player->get_object_id_hash();
|
||||
resp.state = static_cast<enums::MediaPlayerState>(media_player->state);
|
||||
|
||||
media_player::MediaPlayerState report_state = media_player->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING
|
||||
? media_player::MEDIA_PLAYER_STATE_PLAYING
|
||||
: media_player->state;
|
||||
resp.state = static_cast<enums::MediaPlayerState>(report_state);
|
||||
resp.volume = media_player->volume;
|
||||
resp.muted = media_player->is_muted();
|
||||
return this->send_media_player_state_response(resp);
|
||||
|
@ -1038,6 +1042,9 @@ void APIConnection::media_player_command(const MediaPlayerCommandRequest &msg) {
|
|||
if (msg.has_media_url) {
|
||||
call.set_media_url(msg.media_url);
|
||||
}
|
||||
if (msg.has_announcement) {
|
||||
call.set_announcement(msg.announcement);
|
||||
}
|
||||
call.perform();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5253,6 +5253,14 @@ bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, ProtoVarInt val
|
|||
this->has_media_url = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 8: {
|
||||
this->has_announcement = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
case 9: {
|
||||
this->announcement = value.as_bool();
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
@ -5289,6 +5297,8 @@ void MediaPlayerCommandRequest::encode(ProtoWriteBuffer buffer) const {
|
|||
buffer.encode_float(5, this->volume);
|
||||
buffer.encode_bool(6, this->has_media_url);
|
||||
buffer.encode_string(7, this->media_url);
|
||||
buffer.encode_bool(8, this->has_announcement);
|
||||
buffer.encode_bool(9, this->announcement);
|
||||
}
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void MediaPlayerCommandRequest::dump_to(std::string &out) const {
|
||||
|
@ -5323,6 +5333,14 @@ void MediaPlayerCommandRequest::dump_to(std::string &out) const {
|
|||
out.append(" media_url: ");
|
||||
out.append("'").append(this->media_url).append("'");
|
||||
out.append("\n");
|
||||
|
||||
out.append(" has_announcement: ");
|
||||
out.append(YESNO(this->has_announcement));
|
||||
out.append("\n");
|
||||
|
||||
out.append(" announcement: ");
|
||||
out.append(YESNO(this->announcement));
|
||||
out.append("\n");
|
||||
out.append("}");
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1298,6 +1298,8 @@ class MediaPlayerCommandRequest : public ProtoMessage {
|
|||
float volume{0.0f};
|
||||
bool has_media_url{false};
|
||||
std::string media_url{};
|
||||
bool has_announcement{false};
|
||||
bool announcement{false};
|
||||
void encode(ProtoWriteBuffer buffer) const override;
|
||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||
void dump_to(std::string &out) const override;
|
||||
|
|
|
@ -15,6 +15,7 @@ void CST816Touchscreen::continue_setup_() {
|
|||
}
|
||||
switch (this->chip_id_) {
|
||||
case CST820_CHIP_ID:
|
||||
case CST826_CHIP_ID:
|
||||
case CST716_CHIP_ID:
|
||||
case CST816S_CHIP_ID:
|
||||
case CST816D_CHIP_ID:
|
||||
|
@ -90,6 +91,9 @@ void CST816Touchscreen::dump_config() {
|
|||
case CST820_CHIP_ID:
|
||||
name = "CST820";
|
||||
break;
|
||||
case CST826_CHIP_ID:
|
||||
name = "CST826";
|
||||
break;
|
||||
case CST816S_CHIP_ID:
|
||||
name = "CST816S";
|
||||
break;
|
||||
|
|
|
@ -24,6 +24,7 @@ static const uint8_t REG_SLEEP = 0xE5;
|
|||
static const uint8_t REG_IRQ_CTL = 0xFA;
|
||||
static const uint8_t IRQ_EN_MOTION = 0x70;
|
||||
|
||||
static const uint8_t CST826_CHIP_ID = 0x11;
|
||||
static const uint8_t CST820_CHIP_ID = 0xB7;
|
||||
static const uint8_t CST816S_CHIP_ID = 0xB4;
|
||||
static const uint8_t CST816D_CHIP_ID = 0xB6;
|
||||
|
|
|
@ -8,62 +8,16 @@
|
|||
#include <cinttypes>
|
||||
#include <climits>
|
||||
|
||||
#ifdef USE_ESP32
|
||||
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_system.h>
|
||||
|
||||
#include <esp_chip_info.h>
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
#include <esp32/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
|
||||
#include <esp32c3/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
#include <esp32c6/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
#include <esp32s2/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
#include <esp32s3/rom/rtc.h>
|
||||
#endif
|
||||
|
||||
#endif // USE_ESP32
|
||||
|
||||
#ifdef USE_ARDUINO
|
||||
#ifdef USE_RP2040
|
||||
#include <Arduino.h>
|
||||
#elif defined(USE_ESP32) || defined(USE_ESP8266)
|
||||
#include <Esp.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
static uint32_t get_free_heap() {
|
||||
#if defined(USE_ESP8266)
|
||||
return ESP.getFreeHeap(); // NOLINT(readability-static-accessed-through-instance)
|
||||
#elif defined(USE_ESP32)
|
||||
return heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||||
#elif defined(USE_RP2040)
|
||||
return rp2040.getFreeHeap();
|
||||
#elif defined(USE_LIBRETINY)
|
||||
return lt_heap_get_free();
|
||||
#elif defined(USE_HOST)
|
||||
return INT_MAX;
|
||||
#endif
|
||||
}
|
||||
|
||||
void DebugComponent::dump_config() {
|
||||
#ifndef ESPHOME_LOG_HAS_DEBUG
|
||||
return; // Can't log below if debug logging is disabled
|
||||
#endif
|
||||
|
||||
std::string device_info;
|
||||
std::string reset_reason;
|
||||
device_info.reserve(256);
|
||||
|
||||
ESP_LOGCONFIG(TAG, "Debug component:");
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
LOG_TEXT_SENSOR(" ", "Device info", this->device_info_);
|
||||
|
@ -76,305 +30,15 @@ void DebugComponent::dump_config() {
|
|||
#endif // defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)
|
||||
#endif // USE_SENSOR
|
||||
|
||||
std::string device_info;
|
||||
device_info.reserve(256);
|
||||
ESP_LOGD(TAG, "ESPHome version %s", ESPHOME_VERSION);
|
||||
device_info += ESPHOME_VERSION;
|
||||
|
||||
this->free_heap_ = get_free_heap();
|
||||
this->free_heap_ = get_free_heap_();
|
||||
ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_);
|
||||
|
||||
#if defined(USE_ARDUINO) && (defined(USE_ESP32) || defined(USE_ESP8266))
|
||||
const char *flash_mode;
|
||||
switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance)
|
||||
case FM_QIO:
|
||||
flash_mode = "QIO";
|
||||
break;
|
||||
case FM_QOUT:
|
||||
flash_mode = "QOUT";
|
||||
break;
|
||||
case FM_DIO:
|
||||
flash_mode = "DIO";
|
||||
break;
|
||||
case FM_DOUT:
|
||||
flash_mode = "DOUT";
|
||||
break;
|
||||
#ifdef USE_ESP32
|
||||
case FM_FAST_READ:
|
||||
flash_mode = "FAST_READ";
|
||||
break;
|
||||
case FM_SLOW_READ:
|
||||
flash_mode = "SLOW_READ";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
flash_mode = "UNKNOWN";
|
||||
}
|
||||
ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s",
|
||||
ESP.getFlashChipSize() / 1024, // NOLINT
|
||||
ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT
|
||||
device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT
|
||||
"kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT
|
||||
device_info += flash_mode;
|
||||
#endif // USE_ARDUINO && (USE_ESP32 || USE_ESP8266)
|
||||
|
||||
#ifdef USE_ESP32
|
||||
esp_chip_info_t info;
|
||||
esp_chip_info(&info);
|
||||
const char *model;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
model = "ESP32";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
|
||||
model = "ESP32-C3";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
model = "ESP32-C6";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
model = "ESP32-S2";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
model = "ESP32-S3";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32H2)
|
||||
model = "ESP32-H2";
|
||||
#else
|
||||
model = "UNKNOWN";
|
||||
#endif
|
||||
std::string features;
|
||||
if (info.features & CHIP_FEATURE_EMB_FLASH) {
|
||||
features += "EMB_FLASH,";
|
||||
info.features &= ~CHIP_FEATURE_EMB_FLASH;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_WIFI_BGN) {
|
||||
features += "WIFI_BGN,";
|
||||
info.features &= ~CHIP_FEATURE_WIFI_BGN;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_BLE) {
|
||||
features += "BLE,";
|
||||
info.features &= ~CHIP_FEATURE_BLE;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_BT) {
|
||||
features += "BT,";
|
||||
info.features &= ~CHIP_FEATURE_BT;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_EMB_PSRAM) {
|
||||
features += "EMB_PSRAM,";
|
||||
info.features &= ~CHIP_FEATURE_EMB_PSRAM;
|
||||
}
|
||||
if (info.features)
|
||||
features += "Other:" + format_hex(info.features);
|
||||
ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores,
|
||||
info.revision);
|
||||
device_info += "|Chip: ";
|
||||
device_info += model;
|
||||
device_info += " Features:";
|
||||
device_info += features;
|
||||
device_info += " Cores:" + to_string(info.cores);
|
||||
device_info += " Revision:" + to_string(info.revision);
|
||||
|
||||
ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version());
|
||||
device_info += "|ESP-IDF: ";
|
||||
device_info += esp_get_idf_version();
|
||||
|
||||
std::string mac = get_mac_address_pretty();
|
||||
ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str());
|
||||
device_info += "|EFuse MAC: ";
|
||||
device_info += mac;
|
||||
|
||||
switch (rtc_get_reset_reason(0)) {
|
||||
case POWERON_RESET:
|
||||
reset_reason = "Power On Reset";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SW_RESET:
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case RTC_SW_SYS_RESET:
|
||||
#endif
|
||||
reset_reason = "Software Reset Digital Core";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case OWDT_RESET:
|
||||
reset_reason = "Watch Dog Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
case DEEPSLEEP_RESET:
|
||||
reset_reason = "Deep Sleep Reset Digital Core";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SDIO_RESET:
|
||||
reset_reason = "SLC Module Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
case TG0WDT_SYS_RESET:
|
||||
reset_reason = "Timer Group 0 Watch Dog Reset Digital Core";
|
||||
break;
|
||||
case TG1WDT_SYS_RESET:
|
||||
reset_reason = "Timer Group 1 Watch Dog Reset Digital Core";
|
||||
break;
|
||||
case RTCWDT_SYS_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset Digital Core";
|
||||
break;
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
case INTRUSION_RESET:
|
||||
reset_reason = "Intrusion Reset CPU";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case TGWDT_CPU_RESET:
|
||||
reset_reason = "Timer Group Reset CPU";
|
||||
break;
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case TG0WDT_CPU_RESET:
|
||||
reset_reason = "Timer Group 0 Reset CPU";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SW_CPU_RESET:
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case RTC_SW_CPU_RESET:
|
||||
#endif
|
||||
reset_reason = "Software Reset CPU";
|
||||
break;
|
||||
case RTCWDT_CPU_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset CPU";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case EXT_CPU_RESET:
|
||||
reset_reason = "External CPU Reset";
|
||||
break;
|
||||
#endif
|
||||
case RTCWDT_BROWN_OUT_RESET:
|
||||
reset_reason = "Voltage Unstable Reset";
|
||||
break;
|
||||
case RTCWDT_RTC_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case TG1WDT_CPU_RESET:
|
||||
reset_reason = "Timer Group 1 Reset CPU";
|
||||
break;
|
||||
case SUPER_WDT_RESET:
|
||||
reset_reason = "Super Watchdog Reset Digital Core And RTC Module";
|
||||
break;
|
||||
case GLITCH_RTC_RESET:
|
||||
reset_reason = "Glitch Reset Digital Core And RTC Module";
|
||||
break;
|
||||
case EFUSE_RESET:
|
||||
reset_reason = "eFuse Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case USB_UART_CHIP_RESET:
|
||||
reset_reason = "USB UART Reset Digital Core";
|
||||
break;
|
||||
case USB_JTAG_CHIP_RESET:
|
||||
reset_reason = "USB JTAG Reset Digital Core";
|
||||
break;
|
||||
case POWER_GLITCH_RESET:
|
||||
reset_reason = "Power Glitch Reset Digital Core And RTC Module";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
reset_reason = "Unknown Reset Reason";
|
||||
}
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
|
||||
device_info += "|Reset: ";
|
||||
device_info += reset_reason;
|
||||
|
||||
const char *wakeup_reason;
|
||||
switch (rtc_get_wakeup_cause()) {
|
||||
case NO_SLEEP:
|
||||
wakeup_reason = "No Sleep";
|
||||
break;
|
||||
case EXT_EVENT0_TRIG:
|
||||
wakeup_reason = "External Event 0";
|
||||
break;
|
||||
case EXT_EVENT1_TRIG:
|
||||
wakeup_reason = "External Event 1";
|
||||
break;
|
||||
case GPIO_TRIG:
|
||||
wakeup_reason = "GPIO";
|
||||
break;
|
||||
case TIMER_EXPIRE:
|
||||
wakeup_reason = "Wakeup Timer";
|
||||
break;
|
||||
case SDIO_TRIG:
|
||||
wakeup_reason = "SDIO";
|
||||
break;
|
||||
case MAC_TRIG:
|
||||
wakeup_reason = "MAC";
|
||||
break;
|
||||
case UART0_TRIG:
|
||||
wakeup_reason = "UART0";
|
||||
break;
|
||||
case UART1_TRIG:
|
||||
wakeup_reason = "UART1";
|
||||
break;
|
||||
case TOUCH_TRIG:
|
||||
wakeup_reason = "Touch";
|
||||
break;
|
||||
case SAR_TRIG:
|
||||
wakeup_reason = "SAR";
|
||||
break;
|
||||
case BT_TRIG:
|
||||
wakeup_reason = "BT";
|
||||
break;
|
||||
default:
|
||||
wakeup_reason = "Unknown";
|
||||
}
|
||||
ESP_LOGD(TAG, "Wakeup Reason: %s", wakeup_reason);
|
||||
device_info += "|Wakeup: ";
|
||||
device_info += wakeup_reason;
|
||||
#endif
|
||||
|
||||
#if defined(USE_ESP8266) && !defined(CLANG_TIDY)
|
||||
ESP_LOGD(TAG, "Chip ID: 0x%08X", ESP.getChipId());
|
||||
ESP_LOGD(TAG, "SDK Version: %s", ESP.getSdkVersion());
|
||||
ESP_LOGD(TAG, "Core Version: %s", ESP.getCoreVersion().c_str());
|
||||
ESP_LOGD(TAG, "Boot Version=%u Mode=%u", ESP.getBootVersion(), ESP.getBootMode());
|
||||
ESP_LOGD(TAG, "CPU Frequency: %u", ESP.getCpuFreqMHz());
|
||||
ESP_LOGD(TAG, "Flash Chip ID=0x%08X", ESP.getFlashChipId());
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", ESP.getResetReason().c_str());
|
||||
ESP_LOGD(TAG, "Reset Info: %s", ESP.getResetInfo().c_str());
|
||||
|
||||
device_info += "|Chip: 0x" + format_hex(ESP.getChipId());
|
||||
device_info += "|SDK: ";
|
||||
device_info += ESP.getSdkVersion();
|
||||
device_info += "|Core: ";
|
||||
device_info += ESP.getCoreVersion().c_str();
|
||||
device_info += "|Boot: ";
|
||||
device_info += to_string(ESP.getBootVersion());
|
||||
device_info += "|Mode: " + to_string(ESP.getBootMode());
|
||||
device_info += "|CPU: " + to_string(ESP.getCpuFreqMHz());
|
||||
device_info += "|Flash: 0x" + format_hex(ESP.getFlashChipId());
|
||||
device_info += "|Reset: ";
|
||||
device_info += ESP.getResetReason().c_str();
|
||||
device_info += "|";
|
||||
device_info += ESP.getResetInfo().c_str();
|
||||
|
||||
reset_reason = ESP.getResetReason().c_str();
|
||||
#endif
|
||||
|
||||
#ifdef USE_RP2040
|
||||
ESP_LOGD(TAG, "CPU Frequency: %u", rp2040.f_cpu());
|
||||
device_info += "CPU Frequency: " + to_string(rp2040.f_cpu());
|
||||
#endif // USE_RP2040
|
||||
|
||||
#ifdef USE_LIBRETINY
|
||||
ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version());
|
||||
ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz());
|
||||
ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id());
|
||||
ESP_LOGD(TAG, "Board: %s", lt_get_board_code());
|
||||
ESP_LOGD(TAG, "Flash: %u KiB / RAM: %u KiB", lt_flash_get_size() / 1024, lt_ram_get_size() / 1024);
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", lt_get_reboot_reason_name(lt_get_reboot_reason()));
|
||||
|
||||
device_info += "|Version: ";
|
||||
device_info += LT_BANNER_STR + 10;
|
||||
device_info += "|Reset Reason: ";
|
||||
device_info += lt_get_reboot_reason_name(lt_get_reboot_reason());
|
||||
device_info += "|Chip Name: ";
|
||||
device_info += lt_cpu_get_model_name();
|
||||
device_info += "|Chip ID: 0x" + format_hex(lt_cpu_get_mac_id());
|
||||
device_info += "|Flash: " + to_string(lt_flash_get_size() / 1024) + " KiB";
|
||||
device_info += "|RAM: " + to_string(lt_ram_get_size() / 1024) + " KiB";
|
||||
|
||||
reset_reason = lt_get_reboot_reason_name(lt_get_reboot_reason());
|
||||
#endif // USE_LIBRETINY
|
||||
get_device_info_(device_info);
|
||||
|
||||
#ifdef USE_TEXT_SENSOR
|
||||
if (this->device_info_ != nullptr) {
|
||||
|
@ -383,14 +47,14 @@ void DebugComponent::dump_config() {
|
|||
this->device_info_->publish_state(device_info);
|
||||
}
|
||||
if (this->reset_reason_ != nullptr) {
|
||||
this->reset_reason_->publish_state(reset_reason);
|
||||
this->reset_reason_->publish_state(get_reset_reason_());
|
||||
}
|
||||
#endif // USE_TEXT_SENSOR
|
||||
}
|
||||
|
||||
void DebugComponent::loop() {
|
||||
// log when free heap space has halved
|
||||
uint32_t new_free_heap = get_free_heap();
|
||||
uint32_t new_free_heap = get_free_heap_();
|
||||
if (new_free_heap < this->free_heap_ / 2) {
|
||||
this->free_heap_ = new_free_heap;
|
||||
ESP_LOGD(TAG, "Free Heap Size: %" PRIu32 " bytes", this->free_heap_);
|
||||
|
@ -411,38 +75,16 @@ void DebugComponent::loop() {
|
|||
void DebugComponent::update() {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->free_sensor_ != nullptr) {
|
||||
this->free_sensor_->publish_state(get_free_heap());
|
||||
this->free_sensor_->publish_state(get_free_heap_());
|
||||
}
|
||||
|
||||
if (this->block_sensor_ != nullptr) {
|
||||
#if defined(USE_ESP8266)
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize());
|
||||
#elif defined(USE_ESP32)
|
||||
this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));
|
||||
#elif defined(USE_LIBRETINY)
|
||||
this->block_sensor_->publish_state(lt_heap_get_max_alloc());
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)
|
||||
if (this->fragmentation_sensor_ != nullptr) {
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
this->fragmentation_sensor_->publish_state(ESP.getHeapFragmentation());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (this->loop_time_sensor_ != nullptr) {
|
||||
this->loop_time_sensor_->publish_state(this->max_loop_time_);
|
||||
this->max_loop_time_ = 0;
|
||||
}
|
||||
|
||||
#ifdef USE_ESP32
|
||||
if (this->psram_sensor_ != nullptr) {
|
||||
this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
#endif // USE_ESP32
|
||||
#endif // USE_SENSOR
|
||||
update_platform_();
|
||||
}
|
||||
|
||||
float DebugComponent::get_setup_priority() const { return setup_priority::LATE; }
|
||||
|
|
|
@ -59,6 +59,11 @@ class DebugComponent : public PollingComponent {
|
|||
text_sensor::TextSensor *device_info_{nullptr};
|
||||
text_sensor::TextSensor *reset_reason_{nullptr};
|
||||
#endif // USE_TEXT_SENSOR
|
||||
|
||||
std::string get_reset_reason_();
|
||||
uint32_t get_free_heap_();
|
||||
void get_device_info_(std::string &device_info);
|
||||
void update_platform_();
|
||||
};
|
||||
|
||||
} // namespace debug
|
||||
|
|
|
@ -0,0 +1,287 @@
|
|||
#include "debug_component.h"
|
||||
#ifdef USE_ESP32
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_chip_info.h>
|
||||
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
#include <esp32/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
|
||||
#include <esp32c3/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
#include <esp32c6/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
#include <esp32s2/rom/rtc.h>
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
#include <esp32s3/rom/rtc.h>
|
||||
#endif
|
||||
#ifdef USE_ARDUINO
|
||||
#include <Esp.h>
|
||||
#endif
|
||||
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
std::string DebugComponent::get_reset_reason_() {
|
||||
std::string reset_reason;
|
||||
switch (rtc_get_reset_reason(0)) {
|
||||
case POWERON_RESET:
|
||||
reset_reason = "Power On Reset";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SW_RESET:
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case RTC_SW_SYS_RESET:
|
||||
#endif
|
||||
reset_reason = "Software Reset Digital Core";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case OWDT_RESET:
|
||||
reset_reason = "Watch Dog Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
case DEEPSLEEP_RESET:
|
||||
reset_reason = "Deep Sleep Reset Digital Core";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SDIO_RESET:
|
||||
reset_reason = "SLC Module Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
case TG0WDT_SYS_RESET:
|
||||
reset_reason = "Timer Group 0 Watch Dog Reset Digital Core";
|
||||
break;
|
||||
case TG1WDT_SYS_RESET:
|
||||
reset_reason = "Timer Group 1 Watch Dog Reset Digital Core";
|
||||
break;
|
||||
case RTCWDT_SYS_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset Digital Core";
|
||||
break;
|
||||
#if !defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
case INTRUSION_RESET:
|
||||
reset_reason = "Intrusion Reset CPU";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case TGWDT_CPU_RESET:
|
||||
reset_reason = "Timer Group Reset CPU";
|
||||
break;
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case TG0WDT_CPU_RESET:
|
||||
reset_reason = "Timer Group 0 Reset CPU";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case SW_CPU_RESET:
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case RTC_SW_CPU_RESET:
|
||||
#endif
|
||||
reset_reason = "Software Reset CPU";
|
||||
break;
|
||||
case RTCWDT_CPU_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset CPU";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
case EXT_CPU_RESET:
|
||||
reset_reason = "External CPU Reset";
|
||||
break;
|
||||
#endif
|
||||
case RTCWDT_BROWN_OUT_RESET:
|
||||
reset_reason = "Voltage Unstable Reset";
|
||||
break;
|
||||
case RTCWDT_RTC_RESET:
|
||||
reset_reason = "RTC Watch Dog Reset Digital Core And RTC Module";
|
||||
break;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S2) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case TG1WDT_CPU_RESET:
|
||||
reset_reason = "Timer Group 1 Reset CPU";
|
||||
break;
|
||||
case SUPER_WDT_RESET:
|
||||
reset_reason = "Super Watchdog Reset Digital Core And RTC Module";
|
||||
break;
|
||||
case GLITCH_RTC_RESET:
|
||||
reset_reason = "Glitch Reset Digital Core And RTC Module";
|
||||
break;
|
||||
case EFUSE_RESET:
|
||||
reset_reason = "eFuse Reset Digital Core";
|
||||
break;
|
||||
#endif
|
||||
#if defined(USE_ESP32_VARIANT_ESP32C3) || defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
case USB_UART_CHIP_RESET:
|
||||
reset_reason = "USB UART Reset Digital Core";
|
||||
break;
|
||||
case USB_JTAG_CHIP_RESET:
|
||||
reset_reason = "USB JTAG Reset Digital Core";
|
||||
break;
|
||||
case POWER_GLITCH_RESET:
|
||||
reset_reason = "Power Glitch Reset Digital Core And RTC Module";
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
reset_reason = "Unknown Reset Reason";
|
||||
}
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
|
||||
return reset_reason;
|
||||
}
|
||||
|
||||
uint32_t DebugComponent::get_free_heap_() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL); }
|
||||
|
||||
void DebugComponent::get_device_info_(std::string &device_info) {
|
||||
#if defined(USE_ARDUINO)
|
||||
const char *flash_mode;
|
||||
switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance)
|
||||
case FM_QIO:
|
||||
flash_mode = "QIO";
|
||||
break;
|
||||
case FM_QOUT:
|
||||
flash_mode = "QOUT";
|
||||
break;
|
||||
case FM_DIO:
|
||||
flash_mode = "DIO";
|
||||
break;
|
||||
case FM_DOUT:
|
||||
flash_mode = "DOUT";
|
||||
break;
|
||||
case FM_FAST_READ:
|
||||
flash_mode = "FAST_READ";
|
||||
break;
|
||||
case FM_SLOW_READ:
|
||||
flash_mode = "SLOW_READ";
|
||||
break;
|
||||
default:
|
||||
flash_mode = "UNKNOWN";
|
||||
}
|
||||
ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s",
|
||||
ESP.getFlashChipSize() / 1024, // NOLINT
|
||||
ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT
|
||||
device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT
|
||||
"kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT
|
||||
device_info += flash_mode;
|
||||
#endif
|
||||
|
||||
esp_chip_info_t info;
|
||||
esp_chip_info(&info);
|
||||
const char *model;
|
||||
#if defined(USE_ESP32_VARIANT_ESP32)
|
||||
model = "ESP32";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C3)
|
||||
model = "ESP32-C3";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32C6)
|
||||
model = "ESP32-C6";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S2)
|
||||
model = "ESP32-S2";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32S3)
|
||||
model = "ESP32-S3";
|
||||
#elif defined(USE_ESP32_VARIANT_ESP32H2)
|
||||
model = "ESP32-H2";
|
||||
#else
|
||||
model = "UNKNOWN";
|
||||
#endif
|
||||
std::string features;
|
||||
if (info.features & CHIP_FEATURE_EMB_FLASH) {
|
||||
features += "EMB_FLASH,";
|
||||
info.features &= ~CHIP_FEATURE_EMB_FLASH;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_WIFI_BGN) {
|
||||
features += "WIFI_BGN,";
|
||||
info.features &= ~CHIP_FEATURE_WIFI_BGN;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_BLE) {
|
||||
features += "BLE,";
|
||||
info.features &= ~CHIP_FEATURE_BLE;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_BT) {
|
||||
features += "BT,";
|
||||
info.features &= ~CHIP_FEATURE_BT;
|
||||
}
|
||||
if (info.features & CHIP_FEATURE_EMB_PSRAM) {
|
||||
features += "EMB_PSRAM,";
|
||||
info.features &= ~CHIP_FEATURE_EMB_PSRAM;
|
||||
}
|
||||
if (info.features)
|
||||
features += "Other:" + format_hex(info.features);
|
||||
ESP_LOGD(TAG, "Chip: Model=%s, Features=%s Cores=%u, Revision=%u", model, features.c_str(), info.cores,
|
||||
info.revision);
|
||||
device_info += "|Chip: ";
|
||||
device_info += model;
|
||||
device_info += " Features:";
|
||||
device_info += features;
|
||||
device_info += " Cores:" + to_string(info.cores);
|
||||
device_info += " Revision:" + to_string(info.revision);
|
||||
|
||||
ESP_LOGD(TAG, "ESP-IDF Version: %s", esp_get_idf_version());
|
||||
device_info += "|ESP-IDF: ";
|
||||
device_info += esp_get_idf_version();
|
||||
|
||||
std::string mac = get_mac_address_pretty();
|
||||
ESP_LOGD(TAG, "EFuse MAC: %s", mac.c_str());
|
||||
device_info += "|EFuse MAC: ";
|
||||
device_info += mac;
|
||||
|
||||
device_info += "|Reset: ";
|
||||
device_info += get_reset_reason_();
|
||||
|
||||
const char *wakeup_reason;
|
||||
switch (rtc_get_wakeup_cause()) {
|
||||
case NO_SLEEP:
|
||||
wakeup_reason = "No Sleep";
|
||||
break;
|
||||
case EXT_EVENT0_TRIG:
|
||||
wakeup_reason = "External Event 0";
|
||||
break;
|
||||
case EXT_EVENT1_TRIG:
|
||||
wakeup_reason = "External Event 1";
|
||||
break;
|
||||
case GPIO_TRIG:
|
||||
wakeup_reason = "GPIO";
|
||||
break;
|
||||
case TIMER_EXPIRE:
|
||||
wakeup_reason = "Wakeup Timer";
|
||||
break;
|
||||
case SDIO_TRIG:
|
||||
wakeup_reason = "SDIO";
|
||||
break;
|
||||
case MAC_TRIG:
|
||||
wakeup_reason = "MAC";
|
||||
break;
|
||||
case UART0_TRIG:
|
||||
wakeup_reason = "UART0";
|
||||
break;
|
||||
case UART1_TRIG:
|
||||
wakeup_reason = "UART1";
|
||||
break;
|
||||
case TOUCH_TRIG:
|
||||
wakeup_reason = "Touch";
|
||||
break;
|
||||
case SAR_TRIG:
|
||||
wakeup_reason = "SAR";
|
||||
break;
|
||||
case BT_TRIG:
|
||||
wakeup_reason = "BT";
|
||||
break;
|
||||
default:
|
||||
wakeup_reason = "Unknown";
|
||||
}
|
||||
ESP_LOGD(TAG, "Wakeup Reason: %s", wakeup_reason);
|
||||
device_info += "|Wakeup: ";
|
||||
device_info += wakeup_reason;
|
||||
}
|
||||
|
||||
void DebugComponent::update_platform_() {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->block_sensor_ != nullptr) {
|
||||
this->block_sensor_->publish_state(heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL));
|
||||
}
|
||||
if (this->psram_sensor_ != nullptr) {
|
||||
this->psram_sensor_->publish_state(heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace esphome
|
||||
#endif
|
|
@ -0,0 +1,94 @@
|
|||
#include "debug_component.h"
|
||||
#ifdef USE_ESP8266
|
||||
#include "esphome/core/log.h"
|
||||
#include <Esp.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
std::string DebugComponent::get_reset_reason_() {
|
||||
#if !defined(CLANG_TIDY)
|
||||
return ESP.getResetReason().c_str();
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t DebugComponent::get_free_heap_() {
|
||||
return ESP.getFreeHeap(); // NOLINT(readability-static-accessed-through-instance)
|
||||
}
|
||||
|
||||
void DebugComponent::get_device_info_(std::string &device_info) {
|
||||
const char *flash_mode;
|
||||
switch (ESP.getFlashChipMode()) { // NOLINT(readability-static-accessed-through-instance)
|
||||
case FM_QIO:
|
||||
flash_mode = "QIO";
|
||||
break;
|
||||
case FM_QOUT:
|
||||
flash_mode = "QOUT";
|
||||
break;
|
||||
case FM_DIO:
|
||||
flash_mode = "DIO";
|
||||
break;
|
||||
case FM_DOUT:
|
||||
flash_mode = "DOUT";
|
||||
break;
|
||||
default:
|
||||
flash_mode = "UNKNOWN";
|
||||
}
|
||||
ESP_LOGD(TAG, "Flash Chip: Size=%ukB Speed=%uMHz Mode=%s",
|
||||
ESP.getFlashChipSize() / 1024, // NOLINT
|
||||
ESP.getFlashChipSpeed() / 1000000, flash_mode); // NOLINT
|
||||
device_info += "|Flash: " + to_string(ESP.getFlashChipSize() / 1024) + // NOLINT
|
||||
"kB Speed:" + to_string(ESP.getFlashChipSpeed() / 1000000) + "MHz Mode:"; // NOLINT
|
||||
device_info += flash_mode;
|
||||
|
||||
#if !defined(CLANG_TIDY)
|
||||
auto reset_reason = get_reset_reason_();
|
||||
ESP_LOGD(TAG, "Chip ID: 0x%08X", ESP.getChipId());
|
||||
ESP_LOGD(TAG, "SDK Version: %s", ESP.getSdkVersion());
|
||||
ESP_LOGD(TAG, "Core Version: %s", ESP.getCoreVersion().c_str());
|
||||
ESP_LOGD(TAG, "Boot Version=%u Mode=%u", ESP.getBootVersion(), ESP.getBootMode());
|
||||
ESP_LOGD(TAG, "CPU Frequency: %u", ESP.getCpuFreqMHz());
|
||||
ESP_LOGD(TAG, "Flash Chip ID=0x%08X", ESP.getFlashChipId());
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
|
||||
ESP_LOGD(TAG, "Reset Info: %s", ESP.getResetInfo().c_str());
|
||||
|
||||
device_info += "|Chip: 0x" + format_hex(ESP.getChipId());
|
||||
device_info += "|SDK: ";
|
||||
device_info += ESP.getSdkVersion();
|
||||
device_info += "|Core: ";
|
||||
device_info += ESP.getCoreVersion().c_str();
|
||||
device_info += "|Boot: ";
|
||||
device_info += to_string(ESP.getBootVersion());
|
||||
device_info += "|Mode: " + to_string(ESP.getBootMode());
|
||||
device_info += "|CPU: " + to_string(ESP.getCpuFreqMHz());
|
||||
device_info += "|Flash: 0x" + format_hex(ESP.getFlashChipId());
|
||||
device_info += "|Reset: ";
|
||||
device_info += reset_reason;
|
||||
device_info += "|";
|
||||
device_info += ESP.getResetInfo().c_str();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DebugComponent::update_platform_() {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->block_sensor_ != nullptr) {
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
this->block_sensor_->publish_state(ESP.getMaxFreeBlockSize());
|
||||
}
|
||||
#if USE_ARDUINO_VERSION_CODE >= VERSION_CODE(2, 5, 2)
|
||||
if (this->fragmentation_sensor_ != nullptr) {
|
||||
// NOLINTNEXTLINE(readability-static-accessed-through-instance)
|
||||
this->fragmentation_sensor_->publish_state(ESP.getHeapFragmentation());
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace esphome
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#include "debug_component.h"
|
||||
#ifdef USE_HOST
|
||||
#include <climits>
|
||||
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
std::string DebugComponent::get_reset_reason_() { return ""; }
|
||||
|
||||
uint32_t DebugComponent::get_free_heap_() { return INT_MAX; }
|
||||
|
||||
void DebugComponent::get_device_info_(std::string &device_info) {}
|
||||
|
||||
void DebugComponent::update_platform_() {}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace esphome
|
||||
#endif
|
|
@ -0,0 +1,44 @@
|
|||
#include "debug_component.h"
|
||||
#ifdef USE_LIBRETINY
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
std::string DebugComponent::get_reset_reason_() { return lt_get_reboot_reason_name(lt_get_reboot_reason()); }
|
||||
|
||||
uint32_t DebugComponent::get_free_heap_() { return lt_heap_get_free(); }
|
||||
|
||||
void DebugComponent::get_device_info_(std::string &device_info) {
|
||||
reset_reason = get_reset_reason_();
|
||||
ESP_LOGD(TAG, "LibreTiny Version: %s", lt_get_version());
|
||||
ESP_LOGD(TAG, "Chip: %s (%04x) @ %u MHz", lt_cpu_get_model_name(), lt_cpu_get_model(), lt_cpu_get_freq_mhz());
|
||||
ESP_LOGD(TAG, "Chip ID: 0x%06X", lt_cpu_get_mac_id());
|
||||
ESP_LOGD(TAG, "Board: %s", lt_get_board_code());
|
||||
ESP_LOGD(TAG, "Flash: %u KiB / RAM: %u KiB", lt_flash_get_size() / 1024, lt_ram_get_size() / 1024);
|
||||
ESP_LOGD(TAG, "Reset Reason: %s", reset_reason.c_str());
|
||||
|
||||
device_info += "|Version: ";
|
||||
device_info += LT_BANNER_STR + 10;
|
||||
device_info += "|Reset Reason: ";
|
||||
device_info += reset_reason;
|
||||
device_info += "|Chip Name: ";
|
||||
device_info += lt_cpu_get_model_name();
|
||||
device_info += "|Chip ID: 0x" + format_hex(lt_cpu_get_mac_id());
|
||||
device_info += "|Flash: " + to_string(lt_flash_get_size() / 1024) + " KiB";
|
||||
device_info += "|RAM: " + to_string(lt_ram_get_size() / 1024) + " KiB";
|
||||
}
|
||||
|
||||
void DebugComponent::update_platform_() {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->block_sensor_ != nullptr) {
|
||||
this->block_sensor_->publish_state(lt_heap_get_max_alloc());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace esphome
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
#include "debug_component.h"
|
||||
#ifdef USE_RP2040
|
||||
#include "esphome/core/log.h"
|
||||
#include <Arduino.h>
|
||||
namespace esphome {
|
||||
namespace debug {
|
||||
|
||||
static const char *const TAG = "debug";
|
||||
|
||||
std::string DebugComponent::get_reset_reason_() { return ""; }
|
||||
|
||||
uint32_t DebugComponent::get_free_heap_() { return rp2040.getFreeHeap(); }
|
||||
|
||||
void DebugComponent::get_device_info_(std::string &device_info) {
|
||||
ESP_LOGD(TAG, "CPU Frequency: %u", rp2040.f_cpu());
|
||||
device_info += "CPU Frequency: " + to_string(rp2040.f_cpu());
|
||||
}
|
||||
|
||||
void DebugComponent::update_platform_() {}
|
||||
|
||||
} // namespace debug
|
||||
} // namespace esphome
|
||||
#endif
|
|
@ -1,6 +1,11 @@
|
|||
#ifdef USE_ESP32
|
||||
|
||||
#include "ble.h"
|
||||
|
||||
#ifdef USE_ESP32_VARIANT_ESP32C6
|
||||
#include "const_esp32c6.h"
|
||||
#endif // USE_ESP32_VARIANT_ESP32C6
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
|
@ -114,7 +119,11 @@ bool ESP32BLE::ble_setup_() {
|
|||
if (esp_bt_controller_get_status() != ESP_BT_CONTROLLER_STATUS_ENABLED) {
|
||||
// start bt controller
|
||||
if (esp_bt_controller_get_status() == ESP_BT_CONTROLLER_STATUS_IDLE) {
|
||||
#ifdef USE_ESP32_VARIANT_ESP32C6
|
||||
esp_bt_controller_config_t cfg = BT_CONTROLLER_CONFIG;
|
||||
#else
|
||||
esp_bt_controller_config_t cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
#endif
|
||||
err = esp_bt_controller_init(&cfg);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_bt_controller_init failed: %s", esp_err_to_name(err));
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef USE_ESP32_VARIANT_ESP32C6
|
||||
|
||||
#include <esp_bt.h>
|
||||
|
||||
namespace esphome {
|
||||
namespace esp32_ble {
|
||||
|
||||
static const esp_bt_controller_config_t BT_CONTROLLER_CONFIG = {
|
||||
.config_version = CONFIG_VERSION,
|
||||
.ble_ll_resolv_list_size = CONFIG_BT_LE_LL_RESOLV_LIST_SIZE,
|
||||
.ble_hci_evt_hi_buf_count = DEFAULT_BT_LE_HCI_EVT_HI_BUF_COUNT,
|
||||
.ble_hci_evt_lo_buf_count = DEFAULT_BT_LE_HCI_EVT_LO_BUF_COUNT,
|
||||
.ble_ll_sync_list_cnt = DEFAULT_BT_LE_MAX_PERIODIC_ADVERTISER_LIST,
|
||||
.ble_ll_sync_cnt = DEFAULT_BT_LE_MAX_PERIODIC_SYNCS,
|
||||
.ble_ll_rsp_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT,
|
||||
.ble_ll_adv_dup_list_count = CONFIG_BT_LE_LL_DUP_SCAN_LIST_COUNT,
|
||||
.ble_ll_tx_pwr_dbm = BLE_LL_TX_PWR_DBM_N,
|
||||
.rtc_freq = RTC_FREQ_N,
|
||||
.ble_ll_sca = CONFIG_BT_LE_LL_SCA,
|
||||
.ble_ll_scan_phy_number = BLE_LL_SCAN_PHY_NUMBER_N,
|
||||
.ble_ll_conn_def_auth_pyld_tmo = BLE_LL_CONN_DEF_AUTH_PYLD_TMO_N,
|
||||
.ble_ll_jitter_usecs = BLE_LL_JITTER_USECS_N,
|
||||
.ble_ll_sched_max_adv_pdu_usecs = BLE_LL_SCHED_MAX_ADV_PDU_USECS_N,
|
||||
.ble_ll_sched_direct_adv_max_usecs = BLE_LL_SCHED_DIRECT_ADV_MAX_USECS_N,
|
||||
.ble_ll_sched_adv_max_usecs = BLE_LL_SCHED_ADV_MAX_USECS_N,
|
||||
.ble_scan_rsp_data_max_len = DEFAULT_BT_LE_SCAN_RSP_DATA_MAX_LEN_N,
|
||||
.ble_ll_cfg_num_hci_cmd_pkts = BLE_LL_CFG_NUM_HCI_CMD_PKTS_N,
|
||||
.ble_ll_ctrl_proc_timeout_ms = BLE_LL_CTRL_PROC_TIMEOUT_MS_N,
|
||||
.nimble_max_connections = DEFAULT_BT_LE_MAX_CONNECTIONS,
|
||||
.ble_whitelist_size = DEFAULT_BT_NIMBLE_WHITELIST_SIZE, // NOLINT
|
||||
.ble_acl_buf_size = DEFAULT_BT_LE_ACL_BUF_SIZE,
|
||||
.ble_acl_buf_count = DEFAULT_BT_LE_ACL_BUF_COUNT,
|
||||
.ble_hci_evt_buf_size = DEFAULT_BT_LE_HCI_EVT_BUF_SIZE,
|
||||
.ble_multi_adv_instances = DEFAULT_BT_LE_MAX_EXT_ADV_INSTANCES,
|
||||
.ble_ext_adv_max_size = DEFAULT_BT_LE_EXT_ADV_MAX_SIZE,
|
||||
.controller_task_stack_size = NIMBLE_LL_STACK_SIZE,
|
||||
.controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO,
|
||||
.controller_run_cpu = 0,
|
||||
.enable_qa_test = RUN_QA_TEST,
|
||||
.enable_bqb_test = RUN_BQB_TEST,
|
||||
.enable_uart_hci = HCI_UART_EN,
|
||||
.ble_hci_uart_port = DEFAULT_BT_LE_HCI_UART_PORT,
|
||||
.ble_hci_uart_baud = DEFAULT_BT_LE_HCI_UART_BAUD,
|
||||
.ble_hci_uart_data_bits = DEFAULT_BT_LE_HCI_UART_DATA_BITS,
|
||||
.ble_hci_uart_stop_bits = DEFAULT_BT_LE_HCI_UART_STOP_BITS,
|
||||
.ble_hci_uart_flow_ctrl = DEFAULT_BT_LE_HCI_UART_FLOW_CTRL,
|
||||
.ble_hci_uart_uart_parity = DEFAULT_BT_LE_HCI_UART_PARITY,
|
||||
.enable_tx_cca = DEFAULT_BT_LE_TX_CCA_ENABLED,
|
||||
.cca_rssi_thresh = 256 - DEFAULT_BT_LE_CCA_RSSI_THRESH,
|
||||
.sleep_en = NIMBLE_SLEEP_ENABLE,
|
||||
.coex_phy_coded_tx_rx_time_limit = DEFAULT_BT_LE_COEX_PHY_CODED_TX_RX_TLIM_EFF,
|
||||
.dis_scan_backoff = NIMBLE_DISABLE_SCAN_BACKOFF,
|
||||
.ble_scan_classify_filter_enable = 1,
|
||||
.main_xtal_freq = CONFIG_XTAL_FREQ,
|
||||
.version_num = (uint8_t) efuse_hal_chip_revision(),
|
||||
.cpu_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ,
|
||||
.ignore_wl_for_direct_adv = 0,
|
||||
.enable_pcl = DEFAULT_BT_LE_POWER_CONTROL_ENABLED,
|
||||
.config_magic = CONFIG_MAGIC,
|
||||
};
|
||||
|
||||
} // namespace esp32_ble
|
||||
} // namespace esphome
|
||||
|
||||
#endif // USE_ESP32_VARIANT_ESP32C6
|
|
@ -0,0 +1,32 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import i2c
|
||||
from esphome.const import CONF_ID
|
||||
|
||||
CODEOWNERS = ["@Szewcson"]
|
||||
|
||||
DEPENDENCIES = ["i2c"]
|
||||
MULTI_CONF = True
|
||||
|
||||
CONF_GDK101_ID = "gdk101_id"
|
||||
|
||||
gdk101_ns = cg.esphome_ns.namespace("gdk101")
|
||||
GDK101Component = gdk101_ns.class_(
|
||||
"GDK101Component", cg.PollingComponent, i2c.I2CDevice
|
||||
)
|
||||
|
||||
CONFIG_SCHEMA = (
|
||||
cv.Schema(
|
||||
{
|
||||
cv.GenerateID(): cv.declare_id(GDK101Component),
|
||||
}
|
||||
)
|
||||
.extend(cv.polling_component_schema("60s"))
|
||||
.extend(i2c.i2c_device_schema(0x18))
|
||||
)
|
||||
|
||||
|
||||
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)
|
|
@ -0,0 +1,29 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import binary_sensor
|
||||
from esphome.const import (
|
||||
CONF_VIBRATIONS,
|
||||
DEVICE_CLASS_VIBRATION,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
ICON_VIBRATE,
|
||||
)
|
||||
from . import CONF_GDK101_ID, GDK101Component
|
||||
|
||||
DEPENDENCIES = ["gdk101"]
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_GDK101_ID): cv.use_id(GDK101Component),
|
||||
cv.Required(CONF_VIBRATIONS): binary_sensor.binary_sensor_schema(
|
||||
device_class=DEVICE_CLASS_VIBRATION,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
icon=ICON_VIBRATE,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_GDK101_ID])
|
||||
var = await binary_sensor.new_binary_sensor(config[CONF_VIBRATIONS])
|
||||
cg.add(hub.set_vibration_binary_sensor(var))
|
|
@ -0,0 +1,189 @@
|
|||
#include "gdk101.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace gdk101 {
|
||||
|
||||
static const char *const TAG = "gdk101";
|
||||
static const uint8_t NUMBER_OF_READ_RETRIES = 5;
|
||||
|
||||
void GDK101Component::update() {
|
||||
uint8_t data[2];
|
||||
if (!this->read_dose_1m_(data)) {
|
||||
this->status_set_warning("Failed to read dose 1m");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->read_dose_10m_(data)) {
|
||||
this->status_set_warning("Failed to read dose 10m");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->read_status_(data)) {
|
||||
this->status_set_warning("Failed to read status");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->read_measurement_duration_(data)) {
|
||||
this->status_set_warning("Failed to read measurement duration");
|
||||
return;
|
||||
}
|
||||
this->status_clear_warning();
|
||||
}
|
||||
|
||||
void GDK101Component::setup() {
|
||||
uint8_t data[2];
|
||||
ESP_LOGCONFIG(TAG, "Setting up GDK101...");
|
||||
// first, reset the sensor
|
||||
if (!this->reset_sensor_(data)) {
|
||||
this->status_set_error("Reset failed!");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
// sensor should acknowledge success of the reset procedure
|
||||
if (data[0] != 1) {
|
||||
this->status_set_error("Reset not acknowledged!");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
delay(10);
|
||||
// read firmware version
|
||||
if (!this->read_fw_version_(data)) {
|
||||
this->status_set_error("Failed to read firmware version");
|
||||
this->mark_failed();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void GDK101Component::dump_config() {
|
||||
ESP_LOGCONFIG(TAG, "GDK101:");
|
||||
LOG_I2C_DEVICE(this);
|
||||
if (this->is_failed()) {
|
||||
ESP_LOGE(TAG, "Communication with GDK101 failed!");
|
||||
}
|
||||
#ifdef USE_SENSOR
|
||||
LOG_SENSOR(" ", "Firmware Version", this->fw_version_sensor_);
|
||||
LOG_SENSOR(" ", "Average Radaition Dose per 1 minute", this->rad_1m_sensor_);
|
||||
LOG_SENSOR(" ", "Average Radaition Dose per 10 minutes", this->rad_10m_sensor_);
|
||||
LOG_SENSOR(" ", "Status", this->status_sensor_);
|
||||
LOG_SENSOR(" ", "Measurement Duration", this->measurement_duration_sensor_);
|
||||
#endif // USE_SENSOR
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
LOG_BINARY_SENSOR(" ", "Vibration Status", this->vibration_binary_sensor_);
|
||||
#endif // USE_BINARY_SENSOR
|
||||
}
|
||||
|
||||
float GDK101Component::get_setup_priority() const { return setup_priority::DATA; }
|
||||
|
||||
bool GDK101Component::read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len) {
|
||||
uint8_t retry = NUMBER_OF_READ_RETRIES;
|
||||
bool status = false;
|
||||
while (!status && retry) {
|
||||
status = this->read_bytes(a_register, data, len);
|
||||
retry--;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool GDK101Component::reset_sensor_(uint8_t *data) {
|
||||
// It looks like reset is not so well designed in that sensor
|
||||
// After sending reset command it looks that sensor start performing reset and is unresponsible during read
|
||||
// after a while we can send another reset command and read "0x01" as confirmation
|
||||
// Documentation not going in to such details unfortunately
|
||||
if (!this->read_bytes_with_retry_(GDK101_REG_RESET, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDK101Component::read_dose_1m_(uint8_t *data) {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->rad_1m_sensor_ != nullptr) {
|
||||
if (!this->read_bytes(GDK101_REG_READ_1MIN_AVG, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
const float dose = data[0] + (data[1] / 100.0f);
|
||||
|
||||
this->rad_1m_sensor_->publish_state(dose);
|
||||
}
|
||||
#endif // USE_SENSOR
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDK101Component::read_dose_10m_(uint8_t *data) {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->rad_10m_sensor_ != nullptr) {
|
||||
if (!this->read_bytes(GDK101_REG_READ_10MIN_AVG, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
const float dose = data[0] + (data[1] / 100.0f);
|
||||
|
||||
this->rad_10m_sensor_->publish_state(dose);
|
||||
}
|
||||
#endif // USE_SENSOR
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDK101Component::read_status_(uint8_t *data) {
|
||||
if (!this->read_bytes(GDK101_REG_READ_STATUS, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef USE_SENSOR
|
||||
if (this->status_sensor_ != nullptr) {
|
||||
this->status_sensor_->publish_state(data[0]);
|
||||
}
|
||||
#endif // USE_SENSOR
|
||||
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
if (this->vibration_binary_sensor_ != nullptr) {
|
||||
this->vibration_binary_sensor_->publish_state(data[1]);
|
||||
}
|
||||
#endif // USE_BINARY_SENSOR
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDK101Component::read_fw_version_(uint8_t *data) {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->fw_version_sensor_ != nullptr) {
|
||||
if (!this->read_bytes(GDK101_REG_READ_FIRMWARE, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
const float fw_version = data[0] + (data[1] / 10.0f);
|
||||
|
||||
this->fw_version_sensor_->publish_state(fw_version);
|
||||
}
|
||||
#endif // USE_SENSOR
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GDK101Component::read_measurement_duration_(uint8_t *data) {
|
||||
#ifdef USE_SENSOR
|
||||
if (this->measurement_duration_sensor_ != nullptr) {
|
||||
if (!this->read_bytes(GDK101_REG_READ_MEASURING_TIME, data, 2)) {
|
||||
ESP_LOGE(TAG, "Updating GDK101 failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
const float meas_time = (data[0] * 60) + data[1];
|
||||
|
||||
this->measurement_duration_sensor_->publish_state(meas_time);
|
||||
}
|
||||
#endif // USE_SENSOR
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gdk101
|
||||
} // namespace esphome
|
|
@ -0,0 +1,52 @@
|
|||
#pragma once
|
||||
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/defines.h"
|
||||
#ifdef USE_SENSOR
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#endif // USE_SENSOR
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
#include "esphome/components/binary_sensor/binary_sensor.h"
|
||||
#endif // USE_BINARY_SENSOR
|
||||
#include "esphome/components/i2c/i2c.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace gdk101 {
|
||||
|
||||
static const uint8_t GDK101_REG_READ_FIRMWARE = 0xB4; // Firmware version
|
||||
static const uint8_t GDK101_REG_RESET = 0xA0; // Reset register - reading its value triggers reset
|
||||
static const uint8_t GDK101_REG_READ_STATUS = 0xB0; // Status register
|
||||
static const uint8_t GDK101_REG_READ_MEASURING_TIME = 0xB1; // Mesuring time
|
||||
static const uint8_t GDK101_REG_READ_10MIN_AVG = 0xB2; // Average radiation dose per 10 min
|
||||
static const uint8_t GDK101_REG_READ_1MIN_AVG = 0xB3; // Average radiation dose per 1 min
|
||||
|
||||
class GDK101Component : public PollingComponent, public i2c::I2CDevice {
|
||||
#ifdef USE_SENSOR
|
||||
SUB_SENSOR(rad_1m)
|
||||
SUB_SENSOR(rad_10m)
|
||||
SUB_SENSOR(status)
|
||||
SUB_SENSOR(fw_version)
|
||||
SUB_SENSOR(measurement_duration)
|
||||
#endif // USE_SENSOR
|
||||
#ifdef USE_BINARY_SENSOR
|
||||
SUB_BINARY_SENSOR(vibration)
|
||||
#endif // USE_BINARY_SENSOR
|
||||
|
||||
public:
|
||||
void setup() override;
|
||||
void dump_config() override;
|
||||
float get_setup_priority() const override;
|
||||
void update() override;
|
||||
|
||||
protected:
|
||||
bool read_bytes_with_retry_(uint8_t a_register, uint8_t *data, uint8_t len);
|
||||
bool reset_sensor_(uint8_t *data);
|
||||
bool read_dose_1m_(uint8_t *data);
|
||||
bool read_dose_10m_(uint8_t *data);
|
||||
bool read_status_(uint8_t *data);
|
||||
bool read_fw_version_(uint8_t *data);
|
||||
bool read_measurement_duration_(uint8_t *data);
|
||||
};
|
||||
|
||||
} // namespace gdk101
|
||||
} // namespace esphome
|
|
@ -0,0 +1,83 @@
|
|||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome.components import sensor
|
||||
from esphome.const import (
|
||||
DEVICE_CLASS_DURATION,
|
||||
DEVICE_CLASS_EMPTY,
|
||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
CONF_MEASUREMENT_DURATION,
|
||||
CONF_STATUS,
|
||||
CONF_VERSION,
|
||||
ICON_RADIOACTIVE,
|
||||
ICON_TIMER,
|
||||
STATE_CLASS_MEASUREMENT,
|
||||
STATE_CLASS_TOTAL_INCREASING,
|
||||
UNIT_MICROSILVERTS_PER_HOUR,
|
||||
UNIT_SECOND,
|
||||
)
|
||||
from . import CONF_GDK101_ID, GDK101Component
|
||||
|
||||
CONF_RADIATION_DOSE_PER_1M = "radiation_dose_per_1m"
|
||||
CONF_RADIATION_DOSE_PER_10M = "radiation_dose_per_10m"
|
||||
|
||||
DEPENDENCIES = ["gdk101"]
|
||||
|
||||
CONFIG_SCHEMA = cv.Schema(
|
||||
{
|
||||
cv.GenerateID(CONF_GDK101_ID): cv.use_id(GDK101Component),
|
||||
cv.Optional(CONF_RADIATION_DOSE_PER_1M): sensor.sensor_schema(
|
||||
icon=ICON_RADIOACTIVE,
|
||||
unit_of_measurement=UNIT_MICROSILVERTS_PER_HOUR,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_EMPTY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
cv.Optional(CONF_RADIATION_DOSE_PER_10M): sensor.sensor_schema(
|
||||
icon=ICON_RADIOACTIVE,
|
||||
unit_of_measurement=UNIT_MICROSILVERTS_PER_HOUR,
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_EMPTY,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
cv.Optional(CONF_VERSION): sensor.sensor_schema(
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
accuracy_decimals=1,
|
||||
),
|
||||
cv.Optional(CONF_STATUS): sensor.sensor_schema(
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
accuracy_decimals=0,
|
||||
),
|
||||
cv.Optional(CONF_MEASUREMENT_DURATION): sensor.sensor_schema(
|
||||
unit_of_measurement=UNIT_SECOND,
|
||||
icon=ICON_TIMER,
|
||||
accuracy_decimals=0,
|
||||
state_class=STATE_CLASS_TOTAL_INCREASING,
|
||||
device_class=DEVICE_CLASS_DURATION,
|
||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async def to_code(config):
|
||||
hub = await cg.get_variable(config[CONF_GDK101_ID])
|
||||
|
||||
if radiation_dose_per_1m := config.get(CONF_RADIATION_DOSE_PER_1M):
|
||||
sens = await sensor.new_sensor(radiation_dose_per_1m)
|
||||
cg.add(hub.set_rad_1m_sensor(sens))
|
||||
|
||||
if radiation_dose_per_10m := config.get(CONF_RADIATION_DOSE_PER_10M):
|
||||
sens = await sensor.new_sensor(radiation_dose_per_10m)
|
||||
cg.add(hub.set_rad_10m_sensor(sens))
|
||||
|
||||
if version_config := config.get(CONF_VERSION):
|
||||
sens = await sensor.new_sensor(version_config)
|
||||
cg.add(hub.set_fw_version_sensor(sens))
|
||||
|
||||
if status_config := config.get(CONF_STATUS):
|
||||
sens = await sensor.new_sensor(status_config)
|
||||
cg.add(hub.set_status_sensor(sens))
|
||||
|
||||
if measurement_duration_config := config.get(CONF_MEASUREMENT_DURATION):
|
||||
sens = await sensor.new_sensor(measurement_duration_config)
|
||||
cg.add(hub.set_measurement_duration_sensor(sens))
|
|
@ -10,6 +10,11 @@ namespace i2s_audio {
|
|||
static const char *const TAG = "audio";
|
||||
|
||||
void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
||||
media_player::MediaPlayerState play_state = media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
if (call.get_announcement().has_value()) {
|
||||
play_state = call.get_announcement().value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING
|
||||
: media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
}
|
||||
if (call.get_media_url().has_value()) {
|
||||
this->current_url_ = call.get_media_url();
|
||||
if (this->i2s_state_ != I2S_STATE_STOPPED && this->audio_ != nullptr) {
|
||||
|
@ -17,7 +22,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
|||
this->audio_->stopSong();
|
||||
}
|
||||
this->audio_->connecttohost(this->current_url_.value().c_str());
|
||||
this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
this->state = play_state;
|
||||
} else {
|
||||
this->start();
|
||||
}
|
||||
|
@ -35,7 +40,7 @@ void I2SAudioMediaPlayer::control(const media_player::MediaPlayerCall &call) {
|
|||
case media_player::MEDIA_PLAYER_COMMAND_PLAY:
|
||||
if (!this->audio_->isRunning())
|
||||
this->audio_->pauseResume();
|
||||
this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
this->state = play_state;
|
||||
break;
|
||||
case media_player::MEDIA_PLAYER_COMMAND_PAUSE:
|
||||
if (this->audio_->isRunning())
|
||||
|
@ -126,7 +131,9 @@ void I2SAudioMediaPlayer::loop() {
|
|||
|
||||
void I2SAudioMediaPlayer::play_() {
|
||||
this->audio_->loop();
|
||||
if (this->state == media_player::MEDIA_PLAYER_STATE_PLAYING && !this->audio_->isRunning()) {
|
||||
if ((this->state == media_player::MEDIA_PLAYER_STATE_PLAYING ||
|
||||
this->state == media_player::MEDIA_PLAYER_STATE_ANNOUNCING) &&
|
||||
!this->audio_->isRunning()) {
|
||||
this->stop();
|
||||
}
|
||||
}
|
||||
|
@ -164,6 +171,10 @@ void I2SAudioMediaPlayer::start_() {
|
|||
if (this->current_url_.has_value()) {
|
||||
this->audio_->connecttohost(this->current_url_.value().c_str());
|
||||
this->state = media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
if (this->is_announcement_.has_value()) {
|
||||
this->state = this->is_announcement_.value() ? media_player::MEDIA_PLAYER_STATE_ANNOUNCING
|
||||
: media_player::MEDIA_PLAYER_STATE_PLAYING;
|
||||
}
|
||||
this->publish_state();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,7 @@ class I2SAudioMediaPlayer : public Component, public media_player::MediaPlayer,
|
|||
HighFrequencyLoopRequester high_freq_;
|
||||
|
||||
optional<std::string> current_url_{};
|
||||
optional<bool> is_announcement_{};
|
||||
};
|
||||
|
||||
} // namespace i2s_audio
|
||||
|
|
|
@ -8,6 +8,9 @@ namespace ltr390 {
|
|||
|
||||
static const char *const TAG = "ltr390";
|
||||
|
||||
static const uint8_t LTR390_WAKEUP_TIME = 10;
|
||||
static const uint8_t LTR390_SETTLE_TIME = 5;
|
||||
|
||||
static const uint8_t LTR390_MAIN_CTRL = 0x00;
|
||||
static const uint8_t LTR390_MEAS_RATE = 0x04;
|
||||
static const uint8_t LTR390_GAIN = 0x05;
|
||||
|
@ -101,21 +104,27 @@ void LTR390Component::read_mode_(int mode_index) {
|
|||
|
||||
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
||||
ctrl[LTR390_CTRL_MODE] = mode;
|
||||
ctrl[LTR390_CTRL_EN] = true;
|
||||
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
||||
|
||||
// After the sensor integration time do the following
|
||||
this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100, [this, mode_index]() {
|
||||
// Read from the sensor
|
||||
std::get<1>(this->mode_funcs_[mode_index])();
|
||||
this->set_timeout(((uint32_t) RESOLUTIONVALUE[this->res_]) * 100 + LTR390_WAKEUP_TIME + LTR390_SETTLE_TIME,
|
||||
[this, mode_index]() {
|
||||
// Read from the sensor
|
||||
std::get<1>(this->mode_funcs_[mode_index])();
|
||||
|
||||
// If there are more modes to read then begin the next
|
||||
// otherwise stop
|
||||
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
||||
this->read_mode_(mode_index + 1);
|
||||
} else {
|
||||
this->reading_ = false;
|
||||
}
|
||||
});
|
||||
// If there are more modes to read then begin the next
|
||||
// otherwise stop
|
||||
if (mode_index + 1 < (int) this->mode_funcs_.size()) {
|
||||
this->read_mode_(mode_index + 1);
|
||||
} else {
|
||||
// put sensor in standby
|
||||
std::bitset<8> ctrl = this->reg(LTR390_MAIN_CTRL).get();
|
||||
ctrl[LTR390_CTRL_EN] = false;
|
||||
this->reg(LTR390_MAIN_CTRL) = ctrl.to_ulong();
|
||||
this->reading_ = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void LTR390Component::setup() {
|
||||
|
|
|
@ -51,12 +51,16 @@ VolumeSetAction = media_player_ns.class_(
|
|||
|
||||
CONF_ON_PLAY = "on_play"
|
||||
CONF_ON_PAUSE = "on_pause"
|
||||
CONF_ON_ANNOUNCEMENT = "on_announcement"
|
||||
CONF_MEDIA_URL = "media_url"
|
||||
|
||||
StateTrigger = media_player_ns.class_("StateTrigger", automation.Trigger.template())
|
||||
IdleTrigger = media_player_ns.class_("IdleTrigger", automation.Trigger.template())
|
||||
PlayTrigger = media_player_ns.class_("PlayTrigger", automation.Trigger.template())
|
||||
PauseTrigger = media_player_ns.class_("PauseTrigger", automation.Trigger.template())
|
||||
AnnoucementTrigger = media_player_ns.class_(
|
||||
"AnnouncementTrigger", automation.Trigger.template()
|
||||
)
|
||||
IsIdleCondition = media_player_ns.class_("IsIdleCondition", automation.Condition)
|
||||
IsPlayingCondition = media_player_ns.class_("IsPlayingCondition", automation.Condition)
|
||||
|
||||
|
@ -75,6 +79,9 @@ async def setup_media_player_core_(var, config):
|
|||
for conf in config.get(CONF_ON_PAUSE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
for conf in config.get(CONF_ON_ANNOUNCEMENT, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [], conf)
|
||||
|
||||
|
||||
async def register_media_player(var, config):
|
||||
|
@ -106,6 +113,11 @@ MEDIA_PLAYER_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
|
|||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PauseTrigger),
|
||||
}
|
||||
),
|
||||
cv.Optional(CONF_ON_ANNOUNCEMENT): automation.validate_automation(
|
||||
{
|
||||
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(AnnoucementTrigger),
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
@ -52,6 +52,7 @@ class StateTrigger : public Trigger<> {
|
|||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(IdleTrigger, IDLE)
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PlayTrigger, PLAYING)
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(PauseTrigger, PAUSED)
|
||||
MEDIA_PLAYER_SIMPLE_STATE_TRIGGER(AnnouncementTrigger, ANNOUNCING)
|
||||
|
||||
template<typename... Ts> class IsIdleCondition : public Condition<Ts...>, public Parented<MediaPlayer> {
|
||||
public:
|
||||
|
|
|
@ -15,6 +15,8 @@ const char *media_player_state_to_string(MediaPlayerState state) {
|
|||
return "PLAYING";
|
||||
case MEDIA_PLAYER_STATE_PAUSED:
|
||||
return "PAUSED";
|
||||
case MEDIA_PLAYER_STATE_ANNOUNCING:
|
||||
return "ANNOUNCING";
|
||||
case MEDIA_PLAYER_STATE_NONE:
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
|
@ -68,6 +70,9 @@ void MediaPlayerCall::perform() {
|
|||
if (this->volume_.has_value()) {
|
||||
ESP_LOGD(TAG, " Volume: %.2f", this->volume_.value());
|
||||
}
|
||||
if (this->announcement_.has_value()) {
|
||||
ESP_LOGD(TAG, " Announcement: %s", this->announcement_.value() ? "yes" : "no");
|
||||
}
|
||||
this->parent_->control(*this);
|
||||
}
|
||||
|
||||
|
@ -108,6 +113,11 @@ MediaPlayerCall &MediaPlayerCall::set_volume(float volume) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
MediaPlayerCall &MediaPlayerCall::set_announcement(bool announce) {
|
||||
this->announcement_ = announce;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void MediaPlayer::add_on_state_callback(std::function<void()> &&callback) {
|
||||
this->state_callback_.add(std::move(callback));
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ enum MediaPlayerState : uint8_t {
|
|||
MEDIA_PLAYER_STATE_NONE = 0,
|
||||
MEDIA_PLAYER_STATE_IDLE = 1,
|
||||
MEDIA_PLAYER_STATE_PLAYING = 2,
|
||||
MEDIA_PLAYER_STATE_PAUSED = 3
|
||||
MEDIA_PLAYER_STATE_PAUSED = 3,
|
||||
MEDIA_PLAYER_STATE_ANNOUNCING = 4
|
||||
};
|
||||
const char *media_player_state_to_string(MediaPlayerState state);
|
||||
|
||||
|
@ -51,12 +52,14 @@ class MediaPlayerCall {
|
|||
MediaPlayerCall &set_media_url(const std::string &url);
|
||||
|
||||
MediaPlayerCall &set_volume(float volume);
|
||||
MediaPlayerCall &set_announcement(bool announce);
|
||||
|
||||
void perform();
|
||||
|
||||
const optional<MediaPlayerCommand> &get_command() const { return command_; }
|
||||
const optional<std::string> &get_media_url() const { return media_url_; }
|
||||
const optional<float> &get_volume() const { return volume_; }
|
||||
const optional<bool> &get_announcement() const { return announcement_; }
|
||||
|
||||
protected:
|
||||
void validate_();
|
||||
|
@ -64,6 +67,7 @@ class MediaPlayerCall {
|
|||
optional<MediaPlayerCommand> command_;
|
||||
optional<std::string> media_url_;
|
||||
optional<float> volume_;
|
||||
optional<bool> announcement_;
|
||||
};
|
||||
|
||||
class MediaPlayer : public EntityBase {
|
||||
|
|
|
@ -96,6 +96,9 @@ void TimeBasedCover::control(const CoverCall &call) {
|
|||
}
|
||||
} else {
|
||||
auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING;
|
||||
if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
|
||||
this->position = pos == COVER_CLOSED ? COVER_OPEN : COVER_CLOSED;
|
||||
}
|
||||
this->target_position_ = pos;
|
||||
this->start_direction_(op);
|
||||
}
|
||||
|
|
|
@ -152,7 +152,7 @@ void VoiceAssistant::loop() {
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
this->set_state_(State::START_PIPELINE, State::START_MICROPHONE);
|
||||
this->set_state_(State::START_MICROPHONE, State::START_PIPELINE);
|
||||
}
|
||||
} else {
|
||||
this->high_freq_.stop();
|
||||
|
@ -318,7 +318,7 @@ void VoiceAssistant::loop() {
|
|||
#endif
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
if (this->media_player_ != nullptr) {
|
||||
playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_PLAYING);
|
||||
playing = (this->media_player_->state == media_player::MediaPlayerState::MEDIA_PLAYER_STATE_ANNOUNCING);
|
||||
}
|
||||
#endif
|
||||
if (playing) {
|
||||
|
@ -514,7 +514,7 @@ void VoiceAssistant::request_start(bool continuous, bool silence_detection) {
|
|||
} else
|
||||
#endif
|
||||
{
|
||||
this->set_state_(State::START_PIPELINE, State::START_MICROPHONE);
|
||||
this->set_state_(State::START_MICROPHONE, State::START_PIPELINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -640,7 +640,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
|
|||
this->defer([this, url]() {
|
||||
#ifdef USE_MEDIA_PLAYER
|
||||
if (this->media_player_ != nullptr) {
|
||||
this->media_player_->make_call().set_media_url(url).perform();
|
||||
this->media_player_->make_call().set_media_url(url).set_announcement(true).perform();
|
||||
}
|
||||
#endif
|
||||
this->tts_end_trigger_->trigger(url);
|
||||
|
|
|
@ -94,10 +94,10 @@ class VoiceAssistant : public Component {
|
|||
uint32_t get_feature_flags() const {
|
||||
uint32_t flags = 0;
|
||||
flags |= VoiceAssistantFeature::FEATURE_VOICE_ASSISTANT;
|
||||
flags |= VoiceAssistantFeature::FEATURE_API_AUDIO;
|
||||
#ifdef USE_SPEAKER
|
||||
if (this->speaker_ != nullptr) {
|
||||
flags |= VoiceAssistantFeature::FEATURE_SPEAKER;
|
||||
flags |= VoiceAssistantFeature::FEATURE_API_AUDIO;
|
||||
}
|
||||
#endif
|
||||
return flags;
|
||||
|
|
|
@ -35,19 +35,19 @@ WebServer = web_server_ns.class_("WebServer", cg.Component, cg.Controller)
|
|||
def default_url(config):
|
||||
config = config.copy()
|
||||
if config[CONF_VERSION] == 1:
|
||||
if not (CONF_CSS_URL in config):
|
||||
if CONF_CSS_URL not in config:
|
||||
config[CONF_CSS_URL] = "https://esphome.io/_static/webserver-v1.min.css"
|
||||
if not (CONF_JS_URL in config):
|
||||
if CONF_JS_URL not in config:
|
||||
config[CONF_JS_URL] = "https://esphome.io/_static/webserver-v1.min.js"
|
||||
if config[CONF_VERSION] == 2:
|
||||
if not (CONF_CSS_URL in config):
|
||||
if CONF_CSS_URL not in config:
|
||||
config[CONF_CSS_URL] = ""
|
||||
if not (CONF_JS_URL in config):
|
||||
if CONF_JS_URL not in config:
|
||||
config[CONF_JS_URL] = "https://oi.esphome.io/v2/www.js"
|
||||
if config[CONF_VERSION] == 3:
|
||||
if not (CONF_CSS_URL in config):
|
||||
if CONF_CSS_URL not in config:
|
||||
config[CONF_CSS_URL] = ""
|
||||
if not (CONF_JS_URL in config):
|
||||
if CONF_JS_URL not in config:
|
||||
config[CONF_JS_URL] = "https://oi.esphome.io/v3/www.js"
|
||||
return config
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ from esphome.voluptuous_schema import ExtraKeysInvalid
|
|||
from esphome.log import color, Fore
|
||||
import esphome.final_validate as fv
|
||||
import esphome.config_validation as cv
|
||||
from esphome.types import ConfigType, ConfigPathType, ConfigFragmentType
|
||||
from esphome.types import ConfigType, ConfigFragmentType
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -148,6 +148,8 @@ class Config(OrderedDict, fv.FinalValidateConfig):
|
|||
path = path or []
|
||||
try:
|
||||
yield
|
||||
except cv.FinalExternalInvalid as e:
|
||||
self.add_error(e)
|
||||
except vol.Invalid as e:
|
||||
e.prepend(path)
|
||||
self.add_error(e)
|
||||
|
@ -211,7 +213,7 @@ class Config(OrderedDict, fv.FinalValidateConfig):
|
|||
return doc_range
|
||||
|
||||
def get_nested_item(
|
||||
self, path: ConfigPathType, raise_error: bool = False
|
||||
self, path: ConfigPath, raise_error: bool = False
|
||||
) -> ConfigFragmentType:
|
||||
data = self
|
||||
for item_index in path:
|
||||
|
@ -242,7 +244,7 @@ class Config(OrderedDict, fv.FinalValidateConfig):
|
|||
return path
|
||||
raise KeyError(f"ID {id} not found in configuration")
|
||||
|
||||
def get_config_for_path(self, path: ConfigPathType) -> ConfigFragmentType:
|
||||
def get_config_for_path(self, path: ConfigPath) -> ConfigFragmentType:
|
||||
return self.get_nested_item(path, raise_error=True)
|
||||
|
||||
@property
|
||||
|
@ -883,6 +885,9 @@ def _get_parent_name(path, config):
|
|||
# Sub-item
|
||||
break
|
||||
return domain
|
||||
# When processing a list, skip back over the index
|
||||
while len(path) > 1 and isinstance(path[-1], int):
|
||||
path = path[:-1]
|
||||
return path[-1]
|
||||
|
||||
|
||||
|
@ -1104,7 +1109,14 @@ def read_config(command_line_substitutions):
|
|||
if errline:
|
||||
errstr += f" {errline}"
|
||||
safe_print(errstr)
|
||||
safe_print(indent(dump_dict(res, path)[0]))
|
||||
split_dump = dump_dict(res, path)[0].splitlines()
|
||||
# find the last error message
|
||||
i = len(split_dump) - 1
|
||||
while i > 10 and "\033[" not in split_dump[i]:
|
||||
i = i - 1
|
||||
# discard lines more than 4 beyond the last error
|
||||
i = min(i + 4, len(split_dump))
|
||||
safe_print(indent("\n".join(split_dump[:i])))
|
||||
|
||||
for err in res.errors:
|
||||
safe_print(color(Fore.BOLD_RED, err.msg))
|
||||
|
|
|
@ -267,6 +267,10 @@ class Required(vol.Required):
|
|||
super().__init__(key, msg=msg)
|
||||
|
||||
|
||||
class FinalExternalInvalid(Invalid):
|
||||
"""Represents an invalid value in the final validation phase where the path should not be prepended."""
|
||||
|
||||
|
||||
def check_not_templatable(value):
|
||||
if isinstance(value, Lambda):
|
||||
raise Invalid("This option is not templatable!")
|
||||
|
|
|
@ -884,6 +884,7 @@ CONF_VALUE_FONT = "value_font"
|
|||
CONF_VARIABLES = "variables"
|
||||
CONF_VARIANT = "variant"
|
||||
CONF_VERSION = "version"
|
||||
CONF_VIBRATIONS = "vibrations"
|
||||
CONF_VISIBLE = "visible"
|
||||
CONF_VISUAL = "visual"
|
||||
CONF_VOLTAGE = "voltage"
|
||||
|
@ -983,6 +984,7 @@ ICON_SIGNAL_DISTANCE_VARIANT = "mdi:signal"
|
|||
ICON_THERMOMETER = "mdi:thermometer"
|
||||
ICON_TIMELAPSE = "mdi:timelapse"
|
||||
ICON_TIMER = "mdi:timer-outline"
|
||||
ICON_VIBRATE = "mdi:vibrate"
|
||||
ICON_WATER = "mdi:water"
|
||||
ICON_WATER_PERCENT = "mdi:water-percent"
|
||||
ICON_WEATHER_SUNSET = "mdi:weather-sunset"
|
||||
|
@ -1024,6 +1026,7 @@ UNIT_METER_PER_SECOND_SQUARED = "m/s²"
|
|||
UNIT_MICROGRAMS_PER_CUBIC_METER = "µg/m³"
|
||||
UNIT_MICROMETER = "µm"
|
||||
UNIT_MICROSIEMENS_PER_CENTIMETER = "µS/cm"
|
||||
UNIT_MICROSILVERTS_PER_HOUR = "µSv/h"
|
||||
UNIT_MICROTESLA = "µT"
|
||||
UNIT_MILLIGRAMS_PER_CUBIC_METER = "mg/m³"
|
||||
UNIT_MILLISECOND = "ms"
|
||||
|
|
|
@ -394,7 +394,7 @@ async def to_code(config):
|
|||
if project_conf := config.get(CONF_PROJECT):
|
||||
cg.add_define("ESPHOME_PROJECT_NAME", project_conf[CONF_NAME])
|
||||
cg.add_define("ESPHOME_PROJECT_VERSION", project_conf[CONF_VERSION])
|
||||
cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:30])
|
||||
cg.add_define("ESPHOME_PROJECT_VERSION_30", project_conf[CONF_VERSION][:29])
|
||||
for conf in project_conf.get(CONF_ON_UPDATE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID])
|
||||
await cg.register_component(trigger, conf)
|
||||
|
|
|
@ -2,7 +2,7 @@ import abc
|
|||
import inspect
|
||||
import math
|
||||
import re
|
||||
from collections.abc import Generator, Sequence
|
||||
from collections.abc import Sequence
|
||||
from typing import Any, Callable, Optional, Union
|
||||
|
||||
from esphome.core import (
|
||||
|
@ -477,6 +477,7 @@ def variable(
|
|||
:param rhs: The expression to place on the right hand side of the assignment.
|
||||
:param type_: Manually define a type for the variable, only use this when it's not possible
|
||||
to do so during config validation phase (for example because of template arguments).
|
||||
:param register: If true register the variable with the core
|
||||
|
||||
:return: The new variable as a MockObj.
|
||||
"""
|
||||
|
@ -492,9 +493,7 @@ def variable(
|
|||
return obj
|
||||
|
||||
|
||||
def with_local_variable(
|
||||
id_: ID, rhs: SafeExpType, callback: Callable[["MockObj"], None], *args
|
||||
) -> None:
|
||||
def with_local_variable(id_: ID, rhs: SafeExpType, callback: Callable, *args) -> None:
|
||||
"""Declare a new variable, not pointer type, in the code generation, within a scoped block
|
||||
The variable is only usable within the callback
|
||||
The callback cannot be async.
|
||||
|
@ -599,6 +598,7 @@ def add_library(name: str, version: Optional[str], repository: Optional[str] = N
|
|||
|
||||
:param name: The name of the library (for example 'AsyncTCP')
|
||||
:param version: The version of the library, may be None.
|
||||
:param repository: The repository for the library
|
||||
"""
|
||||
CORE.add_library(Library(name, version, repository))
|
||||
|
||||
|
@ -654,7 +654,7 @@ async def process_lambda(
|
|||
parameters: list[tuple[SafeExpType, str]],
|
||||
capture: str = "=",
|
||||
return_type: SafeExpType = None,
|
||||
) -> Generator[LambdaExpression, None, None]:
|
||||
) -> Union[LambdaExpression, None]:
|
||||
"""Process the given lambda value into a LambdaExpression.
|
||||
|
||||
This is a coroutine because lambdas can depend on other IDs,
|
||||
|
@ -673,7 +673,7 @@ async def process_lambda(
|
|||
)
|
||||
|
||||
if value is None:
|
||||
return
|
||||
return None
|
||||
parts = value.parts[:]
|
||||
for i, id in enumerate(value.requires_ids):
|
||||
full_id, var = await get_variable_with_full_id(id)
|
||||
|
@ -712,7 +712,7 @@ async def templatable(
|
|||
value: Any,
|
||||
args: list[tuple[SafeExpType, str]],
|
||||
output_type: Optional[SafeExpType],
|
||||
to_exp: Any = None,
|
||||
to_exp: Union[Callable, dict] = None,
|
||||
):
|
||||
"""Generate code for a templatable config option.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ tornado==6.4
|
|||
tzlocal==5.2 # from time
|
||||
tzdata>=2021.1 # from time
|
||||
pyserial==3.5
|
||||
platformio==6.1.13 # When updating platformio, also update Dockerfile
|
||||
platformio==6.1.15 # When updating platformio, also update Dockerfile
|
||||
esptool==4.7.0
|
||||
click==8.1.7
|
||||
esphome-dashboard==20240412.0
|
||||
|
|
|
@ -5,7 +5,7 @@ pyupgrade==3.15.2 # also change in .pre-commit-config.yaml when updating
|
|||
pre-commit
|
||||
|
||||
# Unit tests
|
||||
pytest==8.1.1
|
||||
pytest==8.2.0
|
||||
pytest-cov==4.1.0
|
||||
pytest-mock==3.14.0
|
||||
pytest-asyncio==0.23.6
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
i2c:
|
||||
id: i2c_bus
|
||||
sda: ${i2c_sda}
|
||||
scl: ${i2c_scl}
|
||||
|
||||
gdk101:
|
||||
id: my_gdk101
|
||||
i2c_id: i2c_bus
|
||||
|
||||
sensor:
|
||||
- platform: gdk101
|
||||
gdk101_id: my_gdk101
|
||||
radiation_dose_per_1m:
|
||||
name: Radiation Dose @ 1 min
|
||||
radiation_dose_per_10m:
|
||||
name: Radiation Dose @ 10 min
|
||||
status:
|
||||
name: Status
|
||||
version:
|
||||
name: FW Version
|
||||
measurement_duration:
|
||||
name: Measuring Time
|
||||
|
||||
binary_sensor:
|
||||
- platform: gdk101
|
||||
gdk101_id: my_gdk101
|
||||
vibrations:
|
||||
name: Vibrations
|
|
@ -0,0 +1,5 @@
|
|||
substitutions:
|
||||
i2c_scl: GPIO16
|
||||
i2c_sda: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
|
@ -0,0 +1,5 @@
|
|||
substitutions:
|
||||
i2c_scl: GPIO16
|
||||
i2c_sda: GPIO17
|
||||
|
||||
<<: !include common.yaml
|
|
@ -0,0 +1,5 @@
|
|||
substitutions:
|
||||
i2c_scl: GPIO5
|
||||
i2c_sda: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
|
@ -0,0 +1,5 @@
|
|||
substitutions:
|
||||
i2c_scl: GPIO5
|
||||
i2c_sda: GPIO4
|
||||
|
||||
<<: !include common.yaml
|
Loading…
Reference in New Issue