From 2712c440041cb697af50168fa1f8266d16393fc6 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Fri, 28 Jun 2019 11:29:37 +0200 Subject: [PATCH] Update dependencies (#653) * Update pio dependencies * Platformio 4 * Fixes * Update platformio_api.py * Lint --- esphome/components/api/__init__.py | 7 +-- esphome/components/async_tcp/__init__.py | 13 +++++ esphome/components/fastled_base/__init__.py | 3 +- esphome/components/gps/__init__.py | 2 + esphome/components/mqtt/__init__.py | 3 +- esphome/components/neopixelbus/light.py | 11 ++++- esphome/components/sntp/sntp_component.cpp | 2 +- esphome/components/sun/__init__.py | 5 +- .../components/web_server_base/__init__.py | 5 +- esphome/core.py | 23 +++++++-- esphome/platformio_api.py | 49 ++++++++++--------- esphome/writer.py | 4 +- platformio.ini | 6 +-- requirements.txt | 1 + requirements_test.txt | 3 +- script/.neopixelbus.patch | 35 ++++++++----- setup.py | 1 + 17 files changed, 113 insertions(+), 60 deletions(-) create mode 100644 esphome/components/async_tcp/__init__.py diff --git a/esphome/components/api/__init__.py b/esphome/components/api/__init__.py index ff825693b..b0ae42e48 100644 --- a/esphome/components/api/__init__.py +++ b/esphome/components/api/__init__.py @@ -4,9 +4,10 @@ from esphome import automation from esphome.automation import Condition from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \ CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID, CONF_EVENT -from esphome.core import CORE, coroutine_with_priority +from esphome.core import coroutine_with_priority DEPENDENCIES = ['network'] +AUTO_LOAD = ['async_tcp'] api_ns = cg.esphome_ns.namespace('api') APIServer = api_ns.class_('APIServer', cg.Component, cg.Controller) @@ -67,10 +68,6 @@ def to_code(config): cg.add_define('USE_API') cg.add_global(api_ns.using) - if CORE.is_esp32: - cg.add_library('AsyncTCP', '1.0.3') - elif CORE.is_esp8266: - cg.add_library('ESPAsyncTCP', '1.2.0') KEY_VALUE_SCHEMA = cv.Schema({cv.string: cv.templatable(cv.string)}) diff --git a/esphome/components/async_tcp/__init__.py b/esphome/components/async_tcp/__init__.py new file mode 100644 index 000000000..f2c457e19 --- /dev/null +++ b/esphome/components/async_tcp/__init__.py @@ -0,0 +1,13 @@ +# Dummy integration to allow relying on AsyncTCP +from esphome.core import CORE, coroutine_with_priority +import esphome.codegen as cg + + +@coroutine_with_priority(200.0) +def to_code(config): + if CORE.is_esp32: + # https://github.com/me-no-dev/AsyncTCP/blob/master/library.json + cg.add_library('AsyncTCP', '1.0.3') + elif CORE.is_esp8266: + # https://github.com/me-no-dev/ESPAsyncTCP/blob/master/library.json + cg.add_library('ESPAsyncTCP', '1.2.0') diff --git a/esphome/components/fastled_base/__init__.py b/esphome/components/fastled_base/__init__.py index 7354f9ae9..b552c917c 100644 --- a/esphome/components/fastled_base/__init__.py +++ b/esphome/components/fastled_base/__init__.py @@ -34,5 +34,6 @@ def new_fastled_light(config): cg.add(var.set_max_refresh_rate(config[CONF_MAX_REFRESH_RATE])) yield light.register_light(var, config) - cg.add_library('FastLED', '3.2.0') + # https://github.com/FastLED/FastLED/blob/master/library.json + cg.add_library('FastLED', '3.2.9') yield var diff --git a/esphome/components/gps/__init__.py b/esphome/components/gps/__init__.py index 3ecbc89f7..ec94ebdad 100644 --- a/esphome/components/gps/__init__.py +++ b/esphome/components/gps/__init__.py @@ -20,4 +20,6 @@ def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) yield uart.register_uart_device(var, config) + + # https://platformio.org/lib/show/1655/TinyGPSPlus cg.add_library('TinyGPSPlus', '1.0.2') diff --git a/esphome/components/mqtt/__init__.py b/esphome/components/mqtt/__init__.py index d30e25c18..76c6da112 100644 --- a/esphome/components/mqtt/__init__.py +++ b/esphome/components/mqtt/__init__.py @@ -15,7 +15,7 @@ from esphome.const import CONF_AVAILABILITY, CONF_BIRTH_MESSAGE, CONF_BROKER, CO from esphome.core import coroutine_with_priority, coroutine, CORE DEPENDENCIES = ['network'] -AUTO_LOAD = ['json'] +AUTO_LOAD = ['json', 'async_tcp'] def validate_message_just_topic(value): @@ -154,6 +154,7 @@ def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) yield cg.register_component(var, config) + # https://github.com/marvinroger/async-mqtt-client/blob/master/library.json cg.add_library('AsyncMqttClient', '0.8.2') cg.add_define('USE_MQTT') cg.add_global(mqtt_ns.using) diff --git a/esphome/components/neopixelbus/light.py b/esphome/components/neopixelbus/light.py index 694ac028f..49ea9d237 100644 --- a/esphome/components/neopixelbus/light.py +++ b/esphome/components/neopixelbus/light.py @@ -101,6 +101,14 @@ ESP8266_METHODS = { ESP32_METHODS = { 'ESP32_I2S_0': 'NeoEsp32I2s0{}Method', 'ESP32_I2S_1': 'NeoEsp32I2s1{}Method', + 'ESP32_RMT_0': 'NeoEsp32Rmt0{}Method', + 'ESP32_RMT_1': 'NeoEsp32Rmt1{}Method', + 'ESP32_RMT_2': 'NeoEsp32Rmt2{}Method', + 'ESP32_RMT_3': 'NeoEsp32Rmt3{}Method', + 'ESP32_RMT_4': 'NeoEsp32Rmt4{}Method', + 'ESP32_RMT_5': 'NeoEsp32Rmt5{}Method', + 'ESP32_RMT_6': 'NeoEsp32Rmt6{}Method', + 'ESP32_RMT_7': 'NeoEsp32Rmt7{}Method', 'BIT_BANG': 'NeoEsp32BitBang{}Method', } @@ -160,4 +168,5 @@ def to_code(config): cg.add(var.set_pixel_order(getattr(ESPNeoPixelOrder, config[CONF_TYPE]))) - cg.add_library('NeoPixelBus', '2.4.1') + # https://github.com/Makuna/NeoPixelBus/blob/master/library.json + cg.add_library('NeoPixelBus', '2.5.0') diff --git a/esphome/components/sntp/sntp_component.cpp b/esphome/components/sntp/sntp_component.cpp index 4f931203f..c10a3e5ac 100644 --- a/esphome/components/sntp/sntp_component.cpp +++ b/esphome/components/sntp/sntp_component.cpp @@ -2,7 +2,7 @@ #include "esphome/core/log.h" #ifdef ARDUINO_ARCH_ESP32 -#include "apps/sntp/sntp.h" +#include "lwip/apps/sntp.h" #endif #ifdef ARDUINO_ARCH_ESP8266 #include "sntp.h" diff --git a/esphome/components/sun/__init__.py b/esphome/components/sun/__init__.py index 0bcdedcab..fef090218 100644 --- a/esphome/components/sun/__init__.py +++ b/esphome/components/sun/__init__.py @@ -3,6 +3,7 @@ import esphome.config_validation as cv from esphome import automation from esphome.components import time from esphome.const import CONF_TIME_ID, CONF_ID, CONF_TRIGGER_ID +from esphome.py_compat import string_types sun_ns = cg.esphome_ns.namespace('sun') @@ -31,9 +32,9 @@ ELEVATION_MAP = { def elevation(value): - if isinstance(value, str): + if isinstance(value, string_types): try: - value = ELEVATION_MAP[cv.one_of(*ELEVATION_MAP, lower=True, space='_')] + value = ELEVATION_MAP[cv.one_of(*ELEVATION_MAP, lower=True, space='_')(value)] except cv.Invalid: pass value = cv.angle(value) diff --git a/esphome/components/web_server_base/__init__.py b/esphome/components/web_server_base/__init__.py index 71a9cc257..db6c256a9 100644 --- a/esphome/components/web_server_base/__init__.py +++ b/esphome/components/web_server_base/__init__.py @@ -3,7 +3,7 @@ import esphome.codegen as cg from esphome.const import CONF_ID from esphome.core import coroutine_with_priority, CORE -DEPENDENCIES = ['network'] +DEPENDENCIES = ['network', 'async_tcp'] web_server_base_ns = cg.esphome_ns.namespace('web_server_base') WebServerBase = web_server_base_ns.class_('WebServerBase', cg.Component) @@ -21,4 +21,5 @@ def to_code(config): if CORE.is_esp32: cg.add_library('FS', None) - cg.add_library('ESP Async WebServer', '1.1.1') + # https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/library.json + cg.add_library('ESP Async WebServer', '1.2.2') diff --git a/esphome/core.py b/esphome/core.py index 7aaf6b2c7..814b92802 100644 --- a/esphome/core.py +++ b/esphome/core.py @@ -495,7 +495,7 @@ class EsphomeCore(object): # A list of statements to insert in the global block (includes and global variables) self.global_statements = [] # type: List[Statement] # A set of platformio libraries to add to the project - self.libraries = set() # type: Set[Library] + self.libraries = [] # type: List[Library] # A set of build flags to set in the platformio project self.build_flags = set() # type: Set[str] # A set of defines to set for the compile process in esphome/core/defines.h @@ -522,7 +522,7 @@ class EsphomeCore(object): self.variables = {} self.main_statements = [] self.global_statements = [] - self.libraries = set() + self.libraries = [] self.build_flags = set() self.defines = set() self.active_coroutines = {} @@ -666,8 +666,25 @@ class EsphomeCore(object): if not isinstance(library, Library): raise ValueError(u"Library {} must be instance of Library, not {}" u"".format(library, type(library))) - self.libraries.add(library) _LOGGER.debug("Adding library: %s", library) + for other in self.libraries[:]: + if other.name != library.name: + continue + if library.version is None: + # Other requirement is more specific + break + if other.version is None: + # Found more specific version requirement + self.libraries.remove(other) + continue + if other.version == library.version: + break + + raise ValueError(u"Version pinning failed! Libraries {} and {} " + u"requested with conflicting versions!" + u"".format(library, other)) + else: + self.libraries.append(library) return library def add_build_flag(self, build_flag): diff --git a/esphome/platformio_api.py b/esphome/platformio_api.py index 1656f1ad3..f113d3067 100644 --- a/esphome/platformio_api.py +++ b/esphome/platformio_api.py @@ -7,21 +7,28 @@ import re import subprocess from esphome.core import CORE -from esphome.py_compat import IS_PY2 from esphome.util import run_external_command, run_external_process _LOGGER = logging.getLogger(__name__) +def is_platformio4(): + from platformio import VERSION + return VERSION[0] >= 4 + + def patch_structhash(): # Patch platformio's structhash to not recompile the entire project when files are # removed/added. This might have unintended consequences, but this improves compile # times greatly when adding/removing components and a simple clean build solves # all issues - # pylint: disable=no-member,no-name-in-module + # pylint: disable=no-member,no-name-in-module,import-error from platformio.commands import run from platformio import util - from platformio.util import get_project_dir + if is_platformio4(): + from platformio.project.helpers import get_project_dir + else: + from platformio.util import get_project_dir from os.path import join, isdir, getmtime, isfile from os import makedirs @@ -36,7 +43,11 @@ def patch_structhash(): if not isdir(build_dir): makedirs(build_dir) - proj_hash = run.calculate_project_hash() + if is_platformio4(): + from platformio.project import helpers + proj_hash = helpers.calculate_project_hash() + else: + proj_hash = run.calculate_project_hash() # check project structure if isdir(build_dir) and isfile(structhash_file): @@ -48,15 +59,10 @@ def patch_structhash(): f.write(proj_hash) # pylint: disable=protected-access - orig = run._clean_build_dir - - def patched_safe(*args, **kwargs): - try: - return patched_clean_build_dir(*args, **kwargs) - except Exception: # pylint: disable=broad-except - return orig(*args, **kwargs) - - run._clean_build_dir = patched_safe + if is_platformio4(): + run.helpers.clean_build_dir = patched_clean_build_dir + else: + run._clean_build_dir = patched_clean_build_dir def run_platformio_cli(*args, **kwargs): @@ -65,18 +71,13 @@ def run_platformio_cli(*args, **kwargs): os.environ["PLATFORMIO_LIBDEPS_DIR"] = os.path.abspath(CORE.relative_piolibdeps_path()) cmd = ['platformio'] + list(args) - if os.environ.get('ESPHOME_USE_SUBPROCESS') is None: - import platformio.__main__ - try: - if IS_PY2: - patch_structhash() - except Exception: # pylint: disable=broad-except - # Ignore when patch fails - pass - return run_external_command(platformio.__main__.main, - *cmd, **kwargs) + if os.environ.get('ESPHOME_USE_SUBPROCESS') is not None: + return run_external_process(*cmd, **kwargs) - return run_external_process(*cmd, **kwargs) + import platformio.__main__ + patch_structhash() + return run_external_command(platformio.__main__.main, + *cmd, **kwargs) def run_platformio_cli_run(config, verbose, *args, **kwargs): diff --git a/esphome/writer.py b/esphome/writer.py index bda3f09df..ddf75faf6 100644 --- a/esphome/writer.py +++ b/esphome/writer.py @@ -171,9 +171,7 @@ def format_ini(data): def gather_lib_deps(): - lib_deps_l = [x.as_lib_dep for x in CORE.libraries] - lib_deps_l.sort() - return lib_deps_l + return [x.as_lib_dep for x in CORE.libraries] def gather_build_flags(): diff --git a/platformio.ini b/platformio.ini index c5a0d9a21..5e6c64af7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -13,9 +13,9 @@ lib_deps = AsyncTCP@1.0.3 AsyncMqttClient@0.8.2 ArduinoJson-esphomelib@5.13.3 - ESP Async WebServer@1.1.1 - FastLED@3.2.0 - NeoPixelBus@2.4.1 + ESP Async WebServer@1.2.2 + FastLED@3.2.9 + NeoPixelBus@2.5.0 ESPAsyncTCP@1.2.0 TinyGPSPlus@1.0.2 build_flags = diff --git a/requirements.txt b/requirements.txt index 178d3d445..15dac3eb3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,6 +6,7 @@ tornado>=5.1.1,<6 typing>=3.6.6;python_version<"3.5" protobuf>=3.7,<3.8 tzlocal>=1.5.1 +pytz>=2019.1 pyserial>=3.4,<4 ifaddr>=0.1.6,<1 platformio>=3.6.5 ; python_version<"3" diff --git a/requirements_test.txt b/requirements_test.txt index 079b0bf85..110475d34 100644 --- a/requirements_test.txt +++ b/requirements_test.txt @@ -6,9 +6,10 @@ tornado>=5.1.1,<6 typing>=3.6.6 ; python_version<"3.5" protobuf>=3.7,<3.8 tzlocal>=1.5.1 +pytz>=2019.1 pyserial>=3.4,<4 ifaddr>=0.1.6,<1 -platformio>=3.6.5 ; python_version<"3" +platformio>=3.6.7 ; python_version<"3" https://github.com/platformio/platformio-core/archive/develop.zip ; python_version>"3" esptool>=2.6,<3 pylint==1.9.4 ; python_version<"3" diff --git a/script/.neopixelbus.patch b/script/.neopixelbus.patch index 8dc2e74b6..9d52a1f9f 100644 --- a/script/.neopixelbus.patch +++ b/script/.neopixelbus.patch @@ -1,26 +1,35 @@ ---- .piolibdeps/NeoPixelBus_ID547/src/internal/NeoEsp8266DmaMethod.h 2018-12-25 06:37:53.000000000 +0100 -+++ .piolibdeps/NeoPixelBus_ID547/src/internal/NeoEsp8266DmaMethod.h.2 2019-03-01 22:18:10.000000000 +0100 -@@ -169,7 +169,7 @@ +--- .piolibdeps/NeoPixelBus_ID547/src/internal/NeoEsp8266DmaMethod.h 2019-06-25 11:14:33.000000000 +0200 ++++ .piolibdeps/NeoPixelBus_ID547/src/internal/NeoEsp8266DmaMethod.h.2 2019-06-25 11:14:40.000000000 +0200 +@@ -195,7 +195,12 @@ _i2sBufDesc[indexDesc].sub_sof = 0; _i2sBufDesc[indexDesc].datalen = blockSize; _i2sBufDesc[indexDesc].blocksize = blockSize; - _i2sBufDesc[indexDesc].buf_ptr = (uint32_t)is2Buffer; -+ _i2sBufDesc[indexDesc].buf_ptr = is2Buffer; ++ union { ++ uint8_t *ptr; ++ uint32_t value; ++ } ptr; ++ ptr.ptr = is2Buffer; ++ _i2sBufDesc[indexDesc].buf_ptr = ptr.value; _i2sBufDesc[indexDesc].unused = 0; _i2sBufDesc[indexDesc].next_link_ptr = (uint32_t)&(_i2sBufDesc[indexDesc + 1]); - -@@ -329,11 +329,13 @@ + +@@ -361,12 +366,15 @@ + case NeoDmaState_Sending: { - slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA; -+ uint32_t **ptr = reinterpret_cast(&finished_item); -+ uint32_t dat = *reinterpret_cast(ptr); - +- slc_queue_item* finished_item = (slc_queue_item*)SLCRXEDA; +- ++ union { ++ slc_queue_item *ptr; ++ uint32_t value; ++ } ptr; ++ ptr.value = SLCRXEDA; // the data block had actual data sent // point last state block to first state block thus // just looping and not sending the data blocks - (finished_item + 1)->next_link_ptr = (uint32_t)(finished_item); -+ (finished_item + 1)->next_link_ptr = dat; - - s_this->_dmaState = NeoDmaState_Idle; ++ (ptr.ptr + 1)->next_link_ptr = ptr.value; + + s_this->_dmaState = NeoDmaState_Zeroing; } diff --git a/setup.py b/setup.py index a93cd0b32..981db858b 100755 --- a/setup.py +++ b/setup.py @@ -31,6 +31,7 @@ REQUIRES = [ 'typing>=3.6.6;python_version<"3.5"', 'protobuf>=3.7,<3.8', 'tzlocal>=1.5.1', + 'pytz>=2019.1', 'pyserial>=3.4,<4', 'ifaddr>=0.1.6,<1', ]