esphome/esphome/cpp_helpers.py
Otto Winter ac0d921413
ESP-IDF support and generic target platforms (#2303)
* Socket refactor and SSL

* esp-idf temp

* Fixes

* Echo component and noise

* Add noise API transport support

* Updates

* ESP-IDF

* Complete

* Fixes

* Fixes

* Versions update

* New i2c APIs

* Complete i2c refactor

* SPI migration

* Revert ESP Preferences migration, too complex for now

* OTA support

* Remove echo again

* Remove ssl again

* GPIOFlags updates

* Rename esphal and ICACHE_RAM_ATTR

* Make ESP32 arduino compilable again

* Fix GPIO flags

* Complete pin registry refactor and fixes

* Fixes to make test1 compile

* Remove sdkconfig file

* Ignore sdkconfig file

* Fixes in reviewing

* Make test2 compile

* Make test4 compile

* Make test5 compile

* Run clang-format

* Fix lint errors

* Use esp-idf APIs instead of btStart

* Another round of fixes

* Start implementing ESP8266

* Make test3 compile

* Guard esp8266 code

* Lint

* Reformat

* Fixes

* Fixes v2

* more fixes

* ESP-IDF tidy target

* Convert ARDUINO_ARCH_ESPxx

* Update WiFiSignalSensor

* Update time ifdefs

* OTA needs millis from hal

* RestartSwitch needs delay from hal

* ESP-IDF Uart

* Fix OTA blank password

* Allow setting sdkconfig

* Fix idf partitions and allow setting sdkconfig from yaml

* Re-add read/write compat APIs and fix esp8266 uart

* Fix esp8266 store log strings in flash

* Fix ESP32 arduino preferences not initialized

* Update ifdefs

* Change how sdkconfig change is detected

* Add checks to ci-custom and fix them

* Run clang-format

* Add esp-idf clang-tidy target and fix errors

* Fixes from clang-tidy idf round 2

* Fixes from compiling tests with esp-idf

* Run clang-format

* Switch test5.yaml to esp-idf

* Implement ESP8266 Preferences

* Lint

* Re-do PIO package version selection a bit

* Fix arduinoespressif32 package version

* Fix unit tests

* Lint

* Lint fixes

* Fix readv/writev not defined

* Fix graphing component

* Re-add all old options from core/config.py

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
2021-09-20 11:47:51 +02:00

111 lines
3.5 KiB
Python

import logging
from esphome.const import (
CONF_SETUP_PRIORITY,
CONF_UPDATE_INTERVAL,
CONF_TYPE_ID,
)
# pylint: disable=unused-import
from esphome.core import coroutine, ID, CORE
from esphome.types import ConfigType
from esphome.cpp_generator import add, get_variable
from esphome.cpp_types import App
from esphome.util import Registry, RegistryEntry
_LOGGER = logging.getLogger(__name__)
async def gpio_pin_expression(conf):
"""Generate an expression for the given pin option.
This is a coroutine, you must await it with a 'await' expression!
"""
if conf is None:
return None
from esphome import pins
for key, (func, _) in pins.PIN_SCHEMA_REGISTRY.items():
if key in conf:
return await coroutine(func)(conf)
return await coroutine(pins.PIN_SCHEMA_REGISTRY[CORE.target_platform][0])(conf)
async def register_component(var, config):
"""Register the given obj as a component.
This is a coroutine, you must await it with a 'await' expression!
:param var: The variable representing the component.
:param config: The configuration for the component.
"""
import inspect
id_ = str(var.base)
if id_ not in CORE.component_ids:
raise ValueError(
f"Component ID {id_} was not declared to inherit from Component, or was registered twice. Please create a bug report with your configuration."
)
CORE.component_ids.remove(id_)
if CONF_SETUP_PRIORITY in config:
add(var.set_setup_priority(config[CONF_SETUP_PRIORITY]))
if CONF_UPDATE_INTERVAL in config:
add(var.set_update_interval(config[CONF_UPDATE_INTERVAL]))
# Set component source by inspecting the stack and getting the callee module
# https://stackoverflow.com/a/1095621
name = None
try:
for frm in inspect.stack()[1:]:
mod = inspect.getmodule(frm[0])
if mod is None:
continue
name = mod.__name__
if name.startswith("esphome.components."):
name = name[len("esphome.components.") :]
break
if name == "esphome.automation":
name = "automation"
# continue looking further up in stack in case we find a better one
if name == "esphome.coroutine":
# Only works for async-await coroutine syntax
break
except (KeyError, AttributeError, IndexError) as e:
_LOGGER.warning(
"Error while finding name of component, please report this", exc_info=e
)
if name is not None:
add(var.set_component_source(name))
add(App.register_component(var))
return var
async def register_parented(var, value):
if isinstance(value, ID):
paren = await get_variable(value)
else:
paren = value
add(var.set_parent(paren))
def extract_registry_entry_config(registry, full_config):
# type: (Registry, ConfigType) -> RegistryEntry
key, config = next((k, v) for k, v in full_config.items() if k in registry)
return registry[key], config
async def build_registry_entry(registry, full_config):
registry_entry, config = extract_registry_entry_config(registry, full_config)
type_id = full_config[CONF_TYPE_ID]
builder = registry_entry.coroutine_fun
return await builder(config, type_id)
async def build_registry_list(registry, config):
actions = []
for conf in config:
action = await build_registry_entry(registry, conf)
actions.append(action)
return actions