1
0
mirror of https://github.com/esphome/esphome.git synced 2025-09-01 19:02:18 +01:00

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>
This commit is contained in:
Otto Winter
2021-09-20 11:47:51 +02:00
committed by GitHub
parent 1e8e471dec
commit ac0d921413
583 changed files with 9008 additions and 5420 deletions

View File

@@ -531,13 +531,13 @@ class TestEsphomeCore:
assert target.address == "4.3.2.1"
def test_is_esp32(self, target):
target.esp_platform = "ESP32"
target.data[const.KEY_CORE] = {const.KEY_TARGET_PLATFORM: "esp32"}
assert target.is_esp32 is True
assert target.is_esp8266 is False
def test_is_esp8266(self, target):
target.esp_platform = "ESP8266"
target.data[const.KEY_CORE] = {const.KEY_TARGET_PLATFORM: "esp8266"}
assert target.is_esp32 is False
assert target.is_esp8266 is True

View File

@@ -3,7 +3,6 @@ from mock import Mock
from esphome import cpp_helpers as ch
from esphome import const
from esphome.cpp_generator import MockObj
@pytest.mark.asyncio
@@ -13,15 +12,6 @@ async def test_gpio_pin_expression__conf_is_none(monkeypatch):
assert actual is None
@pytest.mark.asyncio
async def test_gpio_pin_expression__new_pin(monkeypatch):
actual = await ch.gpio_pin_expression(
{const.CONF_NUMBER: 42, const.CONF_MODE: "input", const.CONF_INVERTED: False}
)
assert isinstance(actual, MockObj)
@pytest.mark.asyncio
async def test_register_component(monkeypatch):
var = Mock(base="foo.bar")

View File

@@ -1,346 +0,0 @@
"""
Please Note:
These tests cover the process of identifying information about pins, they do not
check if the definition of MCUs and pins is correct.
"""
import logging
import pytest
from esphome.config_validation import Invalid
from esphome.core import EsphomeCore
from esphome import boards, pins
MOCK_ESP8266_BOARD_ID = "_mock_esp8266"
MOCK_ESP8266_PINS = {"X0": 16, "X1": 5, "X2": 4, "LED": 2}
MOCK_ESP8266_BOARD_ALIAS_ID = "_mock_esp8266_alias"
MOCK_ESP8266_FLASH_SIZE = boards.FLASH_SIZE_2_MB
MOCK_ESP32_BOARD_ID = "_mock_esp32"
MOCK_ESP32_PINS = {"Y0": 12, "Y1": 8, "Y2": 3, "LED": 9, "A0": 8}
MOCK_ESP32_BOARD_ALIAS_ID = "_mock_esp32_alias"
UNKNOWN_PLATFORM = "STM32"
@pytest.fixture
def mock_mcu(monkeypatch):
"""
Add a mock MCU into the lists as a stable fixture
"""
boards.ESP8266_BOARD_PINS[MOCK_ESP8266_BOARD_ID] = MOCK_ESP8266_PINS
boards.ESP8266_FLASH_SIZES[MOCK_ESP8266_BOARD_ID] = MOCK_ESP8266_FLASH_SIZE
boards.ESP8266_BOARD_PINS[MOCK_ESP8266_BOARD_ALIAS_ID] = MOCK_ESP8266_BOARD_ID
boards.ESP8266_FLASH_SIZES[MOCK_ESP8266_BOARD_ALIAS_ID] = MOCK_ESP8266_FLASH_SIZE
boards.ESP32_BOARD_PINS[MOCK_ESP32_BOARD_ID] = MOCK_ESP32_PINS
boards.ESP32_BOARD_PINS[MOCK_ESP32_BOARD_ALIAS_ID] = MOCK_ESP32_BOARD_ID
yield
del boards.ESP8266_BOARD_PINS[MOCK_ESP8266_BOARD_ID]
del boards.ESP8266_FLASH_SIZES[MOCK_ESP8266_BOARD_ID]
del boards.ESP8266_BOARD_PINS[MOCK_ESP8266_BOARD_ALIAS_ID]
del boards.ESP8266_FLASH_SIZES[MOCK_ESP8266_BOARD_ALIAS_ID]
del boards.ESP32_BOARD_PINS[MOCK_ESP32_BOARD_ID]
del boards.ESP32_BOARD_PINS[MOCK_ESP32_BOARD_ALIAS_ID]
@pytest.fixture
def core(monkeypatch, mock_mcu):
core = EsphomeCore()
monkeypatch.setattr(pins, "CORE", core)
return core
@pytest.fixture
def core_esp8266(core):
core.esp_platform = "ESP8266"
core.board = MOCK_ESP8266_BOARD_ID
return core
@pytest.fixture
def core_esp32(core):
core.esp_platform = "ESP32"
core.board = MOCK_ESP32_BOARD_ID
return core
class Test_lookup_pin:
@pytest.mark.parametrize(
"value, expected",
(
("X1", 5),
("MOSI", 13),
),
)
def test_valid_esp8266_pin(self, core_esp8266, value, expected):
actual = pins._lookup_pin(value)
assert actual == expected
def test_valid_esp8266_pin_alias(self, core_esp8266):
core_esp8266.board = MOCK_ESP8266_BOARD_ALIAS_ID
actual = pins._lookup_pin("X2")
assert actual == 4
@pytest.mark.parametrize(
"value, expected",
(
("Y1", 8),
("A0", 8),
("MOSI", 23),
),
)
def test_valid_esp32_pin(self, core_esp32, value, expected):
actual = pins._lookup_pin(value)
assert actual == expected
def test_valid_32_pin_alias(self, core_esp32):
core_esp32.board = MOCK_ESP32_BOARD_ALIAS_ID
actual = pins._lookup_pin("Y2")
assert actual == 3
def test_invalid_pin(self, core_esp8266):
with pytest.raises(
Invalid, match="Cannot resolve pin name 'X42' for board _mock_esp8266."
):
pins._lookup_pin("X42")
def test_unsupported_platform(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins._lookup_pin("TX")
class Test_translate_pin:
@pytest.mark.parametrize(
"value, expected",
(
(2, 2),
("3", 3),
("GPIO4", 4),
("TX", 1),
("Y0", 12),
),
)
def test_valid_values(self, core_esp32, value, expected):
actual = pins._translate_pin(value)
assert actual == expected
@pytest.mark.parametrize("value", ({}, None))
def test_invalid_values(self, core_esp32, value):
with pytest.raises(Invalid, match="This variable only supports"):
pins._translate_pin(value)
class Test_validate_gpio_pin:
def test_esp32_valid(self, core_esp32):
actual = pins.validate_gpio_pin("GPIO22")
assert actual == 22
@pytest.mark.parametrize(
"value, match",
(
(-1, "ESP32: Invalid pin number: -1"),
(40, "ESP32: Invalid pin number: 40"),
(6, "This pin cannot be used on ESP32s and"),
(7, "This pin cannot be used on ESP32s and"),
(8, "This pin cannot be used on ESP32s and"),
(11, "This pin cannot be used on ESP32s and"),
(20, "The pin GPIO20 is not usable on ESP32s"),
(24, "The pin GPIO24 is not usable on ESP32s"),
(28, "The pin GPIO28 is not usable on ESP32s"),
(29, "The pin GPIO29 is not usable on ESP32s"),
(30, "The pin GPIO30 is not usable on ESP32s"),
(31, "The pin GPIO31 is not usable on ESP32s"),
),
)
def test_esp32_invalid_pin(self, core_esp32, value, match):
with pytest.raises(Invalid, match=match):
pins.validate_gpio_pin(value)
@pytest.mark.parametrize("value", (9, 10))
def test_esp32_warning(self, core_esp32, caplog, value):
caplog.at_level(logging.WARNING)
pins.validate_gpio_pin(value)
assert len(caplog.messages) == 1
assert caplog.messages[0].endswith("flash interface in QUAD IO flash mode.")
def test_esp8266_valid(self, core_esp8266):
actual = pins.validate_gpio_pin("GPIO12")
assert actual == 12
@pytest.mark.parametrize(
"value, match",
(
(-1, "ESP8266: Invalid pin number: -1"),
(18, "ESP8266: Invalid pin number: 18"),
(6, "This pin cannot be used on ESP8266s and"),
(7, "This pin cannot be used on ESP8266s and"),
(8, "This pin cannot be used on ESP8266s and"),
(11, "This pin cannot be used on ESP8266s and"),
),
)
def test_esp8266_invalid_pin(self, core_esp8266, value, match):
with pytest.raises(Invalid, match=match):
pins.validate_gpio_pin(value)
@pytest.mark.parametrize("value", (9, 10))
def test_esp8266_warning(self, core_esp8266, caplog, value):
caplog.at_level(logging.WARNING)
pins.validate_gpio_pin(value)
assert len(caplog.messages) == 1
assert caplog.messages[0].endswith("flash interface in QUAD IO flash mode.")
def test_unknown_device(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins.validate_gpio_pin("0")
class Test_input_pin:
@pytest.mark.parametrize("value, expected", (("X0", 16),))
def test_valid_esp8266_values(self, core_esp8266, value, expected):
actual = pins.input_pin(value)
assert actual == expected
@pytest.mark.parametrize(
"value, expected",
(
("Y0", 12),
(17, 17),
),
)
def test_valid_esp32_values(self, core_esp32, value, expected):
actual = pins.input_pin(value)
assert actual == expected
@pytest.mark.parametrize("value", (17,))
def test_invalid_esp8266_values(self, core_esp8266, value):
with pytest.raises(Invalid):
pins.input_pin(value)
def test_unknown_platform(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins.input_pin(2)
class Test_input_pullup_pin:
@pytest.mark.parametrize("value, expected", (("X0", 16),))
def test_valid_esp8266_values(self, core_esp8266, value, expected):
actual = pins.input_pullup_pin(value)
assert actual == expected
@pytest.mark.parametrize(
"value, expected",
(
("Y0", 12),
(17, 17),
),
)
def test_valid_esp32_values(self, core_esp32, value, expected):
actual = pins.input_pullup_pin(value)
assert actual == expected
@pytest.mark.parametrize("value", (0,))
def test_invalid_esp8266_values(self, core_esp8266, value):
with pytest.raises(Invalid):
pins.input_pullup_pin(value)
def test_unknown_platform(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins.input_pullup_pin(2)
class Test_output_pin:
@pytest.mark.parametrize("value, expected", (("X0", 16),))
def test_valid_esp8266_values(self, core_esp8266, value, expected):
actual = pins.output_pin(value)
assert actual == expected
@pytest.mark.parametrize(
"value, expected",
(
("Y0", 12),
(17, 17),
),
)
def test_valid_esp32_values(self, core_esp32, value, expected):
actual = pins.output_pin(value)
assert actual == expected
@pytest.mark.parametrize("value", (17,))
def test_invalid_esp8266_values(self, core_esp8266, value):
with pytest.raises(Invalid):
pins.output_pin(value)
@pytest.mark.parametrize("value", range(34, 40))
def test_invalid_esp32_values(self, core_esp32, value):
with pytest.raises(Invalid):
pins.output_pin(value)
def test_unknown_platform(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins.output_pin(2)
class Test_analog_pin:
@pytest.mark.parametrize("value, expected", ((17, 17),))
def test_valid_esp8266_values(self, core_esp8266, value, expected):
actual = pins.analog_pin(value)
assert actual == expected
@pytest.mark.parametrize(
"value, expected",
(
(32, 32),
(39, 39),
),
)
def test_valid_esp32_values(self, core_esp32, value, expected):
actual = pins.analog_pin(value)
assert actual == expected
@pytest.mark.parametrize("value", ("X0",))
def test_invalid_esp8266_values(self, core_esp8266, value):
with pytest.raises(Invalid):
pins.analog_pin(value)
@pytest.mark.parametrize("value", ("Y0",))
def test_invalid_esp32_values(self, core_esp32, value):
with pytest.raises(Invalid):
pins.analog_pin(value)
def test_unknown_platform(self, core):
core.esp_platform = UNKNOWN_PLATFORM
with pytest.raises(NotImplementedError):
pins.analog_pin(2)

View File

@@ -2,7 +2,7 @@
import esphome.wizard as wz
import pytest
from esphome.boards import ESP8266_BOARD_PINS
from esphome.components.esp8266.boards import ESP8266_BOARD_PINS
from mock import MagicMock