1
0
mirror of https://github.com/esphome/esphome.git synced 2025-03-15 15:18:16 +00:00

Merge pull request #23 from esphome/dev

update branch
This commit is contained in:
Michiel van Turnhout 2019-04-03 15:46:53 +02:00 committed by GitHub
commit 676dffb191
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 250 additions and 36 deletions

View File

@ -41,11 +41,11 @@ stages:
- | - |
if [[ "${IS_HASSIO}" == "YES" ]]; then if [[ "${IS_HASSIO}" == "YES" ]]; then
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.1 BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH} BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
DOCKERFILE=docker/Dockerfile.hassio DOCKERFILE=docker/Dockerfile.hassio
else else
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.1 BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3
if [[ "${BUILD_ARCH}" == "amd64" ]]; then if [[ "${BUILD_ARCH}" == "amd64" ]]; then
BUILD_TO=esphome/esphome BUILD_TO=esphome/esphome
else else

View File

@ -1,4 +1,4 @@
ARG BUILD_FROM=esphome/esphome-base-amd64:1.4.1 ARG BUILD_FROM=esphome/esphome-base-amd64:1.4.3
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
COPY . . COPY . .

View File

@ -1,4 +1,4 @@
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.4.1 ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.4.3
FROM ${BUILD_FROM} FROM ${BUILD_FROM}
# Copy root filesystem # Copy root filesystem

View File

@ -16,11 +16,11 @@ echo "PWD: $PWD"
if [[ ${IS_HASSIO} = "YES" ]]; then if [[ ${IS_HASSIO} = "YES" ]]; then
docker build \ docker build \
--build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.1" \ --build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3" \
--build-arg "BUILD_VERSION=${CACHE_TAG}" \ --build-arg "BUILD_VERSION=${CACHE_TAG}" \
-t "${IMAGE_NAME}" -f ../docker/Dockerfile.hassio .. -t "${IMAGE_NAME}" -f ../docker/Dockerfile.hassio ..
else else
docker build \ docker build \
--build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.1" \ --build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3" \
-t "${IMAGE_NAME}" -f ../docker/Dockerfile .. -t "${IMAGE_NAME}" -f ../docker/Dockerfile ..
fi fi

View File

@ -86,7 +86,7 @@ def lib_deps(config):
if CORE.is_esp32: if CORE.is_esp32:
return 'AsyncTCP@1.0.3' return 'AsyncTCP@1.0.3'
if CORE.is_esp8266: if CORE.is_esp8266:
return 'ESPAsyncTCP@1.1.3' return 'ESPAsyncTCP@1.2.0'
raise NotImplementedError raise NotImplementedError

View File

@ -0,0 +1,24 @@
import voluptuous as vol
from esphome.components import binary_sensor
from esphome.components.ttp229_lsf import TTP229LSFComponent, CONF_TTP229_ID
import esphome.config_validation as cv
from esphome.const import CONF_CHANNEL, CONF_NAME
from esphome.cpp_generator import get_variable
DEPENDENCIES = ['ttp229_lsf']
TTP229Channel = binary_sensor.binary_sensor_ns.class_(
'TTP229Channel', binary_sensor.BinarySensor)
PLATFORM_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_PLATFORM_SCHEMA.extend({
cv.GenerateID(): cv.declare_variable_id(TTP229Channel),
cv.GenerateID(CONF_TTP229_ID): cv.use_variable_id(TTP229LSFComponent),
vol.Required(CONF_CHANNEL): vol.All(vol.Coerce(int), vol.Range(min=0, max=15))
}))
def to_code(config):
for hub in get_variable(config[CONF_TTP229_ID]):
yield
rhs = TTP229Channel.new(config[CONF_NAME], config[CONF_CHANNEL])
binary_sensor.register_binary_sensor(hub.add_channel(rhs), config)

View File

@ -46,7 +46,7 @@ def setup_text_sensor_core_(text_sensor_var, config):
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
automation.build_automations(trigger, [(std_string, 'x')], conf) automation.build_automations(trigger, [(std_string, 'x')], conf)
setup_mqtt_component(text_sensor_var.get_mqtt(), config) setup_mqtt_component(text_sensor_var.Pget_mqtt(), config)
def setup_text_sensor(text_sensor_obj, config): def setup_text_sensor(text_sensor_obj, config):

View File

@ -0,0 +1,25 @@
from esphome.components import binary_sensor
import esphome.config_validation as cv
from esphome.const import CONF_ID
from esphome.cpp_generator import Pvariable
from esphome.cpp_helpers import setup_component
from esphome.cpp_types import App, Component
DEPENDENCIES = ['i2c']
CONF_TTP229_ID = 'ttp229_id'
TTP229LSFComponent = binary_sensor.binary_sensor_ns.class_('TTP229LSFComponent', Component)
CONFIG_SCHEMA = cv.Schema({
cv.GenerateID(): cv.declare_variable_id(TTP229LSFComponent),
}).extend(cv.COMPONENT_SCHEMA.schema)
def to_code(config):
rhs = App.make_ttp229_lsf()
var = Pvariable(config[CONF_ID], rhs)
setup_component(var, config)
BUILD_FLAGS = '-DUSE_TTP229_LSF'

View File

@ -433,3 +433,4 @@ ARDUINO_VERSION_ESP32_1_0_1 = 'espressif32@1.6.0'
ARDUINO_VERSION_ESP8266_DEV = 'https://github.com/platformio/platform-espressif8266.git#feature' \ ARDUINO_VERSION_ESP8266_DEV = 'https://github.com/platformio/platform-espressif8266.git#feature' \
'/stage' '/stage'
ARDUINO_VERSION_ESP8266_2_5_0 = 'espressif8266@2.0.0' ARDUINO_VERSION_ESP8266_2_5_0 = 'espressif8266@2.0.0'
ARDUINO_VERSION_ESP8266_2_3_0 = 'espressif8266@1.5.0'

View File

@ -28,7 +28,7 @@ import tornado.websocket
from esphome import const from esphome import const
from esphome.__main__ import get_serial_ports from esphome.__main__ import get_serial_ports
from esphome.helpers import mkdir_p, get_bool_env, run_system_command from esphome.helpers import mkdir_p, get_bool_env, run_system_command
from esphome.py_compat import IS_PY2 from esphome.py_compat import IS_PY2, decode_text
from esphome.storage_json import EsphomeStorageJSON, StorageJSON, \ from esphome.storage_json import EsphomeStorageJSON, StorageJSON, \
esphome_storage_path, ext_storage_path, trash_storage_path esphome_storage_path, ext_storage_path, trash_storage_path
from esphome.util import shlex_quote from esphome.util import shlex_quote
@ -223,8 +223,8 @@ class WizardRequestHandler(BaseHandler):
def post(self): def post(self):
from esphome import wizard from esphome import wizard
kwargs = {k: ''.join(v) for k, v in self.request.arguments.items()} kwargs = {k: u''.join(decode_text(x) for x in v) for k, v in self.request.arguments.items()}
destination = os.path.join(CONFIG_DIR, kwargs['name'] + '.yaml') destination = os.path.join(CONFIG_DIR, kwargs['name'] + u'.yaml')
wizard.wizard_write(path=destination, **kwargs) wizard.wizard_write(path=destination, **kwargs)
self.redirect('/?begin=True') self.redirect('/?begin=True')

View File

@ -195,7 +195,7 @@ def perform_ota(sock, password, file_handle, filename):
send_check(sock, cnonce, 'auth cnonce') send_check(sock, cnonce, 'auth cnonce')
result_md5 = hashlib.md5() result_md5 = hashlib.md5()
result_md5.update(password.encode()) result_md5.update(password.encode('utf-8'))
result_md5.update(nonce.encode()) result_md5.update(nonce.encode())
result_md5.update(cnonce.encode()) result_md5.update(cnonce.encode())
result = result_md5.hexdigest() result = result_md5.hexdigest()

View File

@ -140,16 +140,3 @@ def get_bool_env(var, default=False):
def is_hassio(): def is_hassio():
return get_bool_env('ESPHOME_IS_HASSIO') return get_bool_env('ESPHOME_IS_HASSIO')
def symlink(src, dst):
if hasattr(os, 'symlink'):
os.symlink(src, dst)
else:
import ctypes
csl = ctypes.windll.kernel32.CreateSymbolicLinkW
csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
csl.restype = ctypes.c_ubyte
flags = 1 if os.path.isdir(src) else 0
if csl(dst, src, flags) == 0:
raise ctypes.WinError()

View File

@ -69,3 +69,13 @@ def indexbytes(buf, i):
return buf[i] return buf[i]
else: else:
return ord(buf[i]) return ord(buf[i])
if IS_PY2:
def decode_text(data, encoding='utf-8', errors='strict'):
# type: (str, str, str) -> unicode
return unicode(data, encoding='utf-8', errors=errors)
else:
def decode_text(data, encoding='utf-8', errors='strict'):
# type: (bytes, str, str) -> str
return data.decode(encoding='utf-8', errors=errors)

164
esphome/symlink_ops.py Normal file
View File

@ -0,0 +1,164 @@
import os
if hasattr(os, 'symlink'):
def symlink(src, dst):
return os.symlink(src, dst)
def islink(path):
return os.path.islink(path)
def readlink(path):
return os.readlink(path)
def unlink(path):
return os.unlink(path)
else:
import ctypes
from ctypes import wintypes
# Code taken from
# https://stackoverflow.com/questions/27972776/having-trouble-implementing-a-readlink-function
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
FILE_READ_ATTRIBUTES = 0x0080
OPEN_EXISTING = 3
FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
IO_REPARSE_TAG_MOUNT_POINT = 0xA0000003
IO_REPARSE_TAG_SYMLINK = 0xA000000C
FSCTL_GET_REPARSE_POINT = 0x000900A8
MAXIMUM_REPARSE_DATA_BUFFER_SIZE = 0x4000
LPDWORD = ctypes.POINTER(wintypes.DWORD)
LPWIN32_FIND_DATA = ctypes.POINTER(wintypes.WIN32_FIND_DATAW)
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
def IsReparseTagNameSurrogate(tag):
return bool(tag & 0x20000000)
def _check_invalid_handle(result, func, args):
if result == INVALID_HANDLE_VALUE:
raise ctypes.WinError(ctypes.get_last_error())
return args
def _check_bool(result, func, args):
if not result:
raise ctypes.WinError(ctypes.get_last_error())
return args
kernel32.FindFirstFileW.errcheck = _check_invalid_handle
kernel32.FindFirstFileW.restype = wintypes.HANDLE
kernel32.FindFirstFileW.argtypes = (
wintypes.LPCWSTR, # _In_ lpFileName
LPWIN32_FIND_DATA) # _Out_ lpFindFileData
kernel32.FindClose.argtypes = (
wintypes.HANDLE,) # _Inout_ hFindFile
kernel32.CreateFileW.errcheck = _check_invalid_handle
kernel32.CreateFileW.restype = wintypes.HANDLE
kernel32.CreateFileW.argtypes = (
wintypes.LPCWSTR, # _In_ lpFileName
wintypes.DWORD, # _In_ dwDesiredAccess
wintypes.DWORD, # _In_ dwShareMode
wintypes.LPVOID, # _In_opt_ lpSecurityAttributes
wintypes.DWORD, # _In_ dwCreationDisposition
wintypes.DWORD, # _In_ dwFlagsAndAttributes
wintypes.HANDLE) # _In_opt_ hTemplateFile
kernel32.CloseHandle.argtypes = (
wintypes.HANDLE,) # _In_ hObject
kernel32.DeviceIoControl.errcheck = _check_bool
kernel32.DeviceIoControl.argtypes = (
wintypes.HANDLE, # _In_ hDevice
wintypes.DWORD, # _In_ dwIoControlCode
wintypes.LPVOID, # _In_opt_ lpInBuffer
wintypes.DWORD, # _In_ nInBufferSize
wintypes.LPVOID, # _Out_opt_ lpOutBuffer
wintypes.DWORD, # _In_ nOutBufferSize
LPDWORD, # _Out_opt_ lpBytesReturned
wintypes.LPVOID) # _Inout_opt_ lpOverlapped
class REPARSE_DATA_BUFFER(ctypes.Structure):
class ReparseData(ctypes.Union):
class LinkData(ctypes.Structure):
_fields_ = (('SubstituteNameOffset', wintypes.USHORT),
('SubstituteNameLength', wintypes.USHORT),
('PrintNameOffset', wintypes.USHORT),
('PrintNameLength', wintypes.USHORT))
@property
def PrintName(self):
dt = wintypes.WCHAR * (self.PrintNameLength // ctypes.sizeof(wintypes.WCHAR))
name = dt.from_address(ctypes.addressof(self.PathBuffer) +
self.PrintNameOffset).value
if name.startswith(r'\??'):
name = r'\\?' + name[3:] # NT => Windows
return name
class SymbolicLinkData(LinkData):
_fields_ = (('Flags', wintypes.ULONG), ('PathBuffer', wintypes.BYTE * 0))
class MountPointData(LinkData):
_fields_ = (('PathBuffer', wintypes.BYTE * 0),)
class GenericData(ctypes.Structure):
_fields_ = (('DataBuffer', wintypes.BYTE * 0),)
_fields_ = (('SymbolicLinkReparseBuffer', SymbolicLinkData),
('MountPointReparseBuffer', MountPointData),
('GenericReparseBuffer', GenericData))
_fields_ = (('ReparseTag', wintypes.ULONG),
('ReparseDataLength', wintypes.USHORT),
('Reserved', wintypes.USHORT),
('ReparseData', ReparseData))
_anonymous_ = ('ReparseData',)
def symlink(src, dst):
csl = ctypes.windll.kernel32.CreateSymbolicLinkW
csl.argtypes = (ctypes.c_wchar_p, ctypes.c_wchar_p, ctypes.c_uint32)
csl.restype = ctypes.c_ubyte
flags = 1 if os.path.isdir(src) else 0
if csl(dst, src, flags) == 0:
error = ctypes.WinError()
# pylint: disable=no-member
if error.winerror == 1314 and error.errno == 22:
from esphome.core import EsphomeError
raise EsphomeError("Cannot create symlink from '%s' to '%s'. Try running tool \
with elevated privileges" % (src, dst))
raise error
def islink(path):
if not os.path.isdir(path):
return False
data = wintypes.WIN32_FIND_DATAW()
kernel32.FindClose(kernel32.FindFirstFileW(path, ctypes.byref(data)))
if not data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT:
return False
return IsReparseTagNameSurrogate(data.dwReserved0)
def readlink(path):
n = wintypes.DWORD()
buf = (wintypes.BYTE * MAXIMUM_REPARSE_DATA_BUFFER_SIZE)()
flags = FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS
handle = kernel32.CreateFileW(path, FILE_READ_ATTRIBUTES, 0, None,
OPEN_EXISTING, flags, None)
try:
kernel32.DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, None, 0,
buf, ctypes.sizeof(buf), ctypes.byref(n), None)
finally:
kernel32.CloseHandle(handle)
rb = REPARSE_DATA_BUFFER.from_buffer(buf)
tag = rb.ReparseTag
if tag == IO_REPARSE_TAG_SYMLINK:
return rb.SymbolicLinkReparseBuffer.PrintName
if tag == IO_REPARSE_TAG_MOUNT_POINT:
return rb.MountPointReparseBuffer.PrintName
if not IsReparseTagNameSurrogate(tag):
raise ValueError("not a link")
raise ValueError("unsupported reparse tag: %d" % tag)
def unlink(path):
return os.rmdir(path)

View File

@ -79,7 +79,7 @@ def wizard_write(path, **kwargs):
kwargs['platform'] = 'ESP8266' if board in ESP8266_BOARD_PINS else 'ESP32' kwargs['platform'] = 'ESP8266' if board in ESP8266_BOARD_PINS else 'ESP32'
platform = kwargs['platform'] platform = kwargs['platform']
with codecs.open(path, 'w') as f_handle: with codecs.open(path, 'w', 'utf-8') as f_handle:
f_handle.write(wizard_file(**kwargs)) f_handle.write(wizard_file(**kwargs))
storage = StorageJSON.from_wizard(name, name + '.local', platform, board) storage = StorageJSON.from_wizard(name, name + '.local', platform, board)
storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path)) storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path))

View File

@ -10,10 +10,12 @@ import shutil
from esphome.config import iter_components from esphome.config import iter_components
from esphome.const import ARDUINO_VERSION_ESP32_1_0_0, ARDUINO_VERSION_ESP8266_2_5_0, \ from esphome.const import ARDUINO_VERSION_ESP32_1_0_0, ARDUINO_VERSION_ESP8266_2_5_0, \
ARDUINO_VERSION_ESP8266_DEV, CONF_BOARD_FLASH_MODE, CONF_BRANCH, CONF_COMMIT, CONF_ESPHOME, \ ARDUINO_VERSION_ESP8266_DEV, CONF_BOARD_FLASH_MODE, CONF_BRANCH, CONF_COMMIT, CONF_ESPHOME, \
CONF_LOCAL, CONF_PLATFORMIO_OPTIONS, CONF_REPOSITORY, CONF_TAG, CONF_USE_CUSTOM_CODE CONF_LOCAL, CONF_PLATFORMIO_OPTIONS, CONF_REPOSITORY, CONF_TAG, CONF_USE_CUSTOM_CODE, \
ARDUINO_VERSION_ESP8266_2_3_0
from esphome.core import CORE, EsphomeError from esphome.core import CORE, EsphomeError
from esphome.core_config import GITHUB_ARCHIVE_ZIP, LIBRARY_URI_REPO, VERSION_REGEX from esphome.core_config import GITHUB_ARCHIVE_ZIP, LIBRARY_URI_REPO, VERSION_REGEX
from esphome.helpers import mkdir_p, run_system_command, symlink from esphome.helpers import mkdir_p, run_system_command
from esphome.symlink_ops import symlink, islink, readlink, unlink
from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS from esphome.pins import ESP8266_FLASH_SIZES, ESP8266_LD_SCRIPTS
from esphome.py_compat import IS_PY3, string_types from esphome.py_compat import IS_PY3, string_types
from esphome.storage_json import StorageJSON, storage_path from esphome.storage_json import StorageJSON, storage_path
@ -220,10 +222,10 @@ def symlink_esphome_core_version(esphome_core_version):
if CORE.is_local_esphome_core_copy: if CORE.is_local_esphome_core_copy:
src_path = CORE.relative_path(esphome_core_version[CONF_LOCAL]) src_path = CORE.relative_path(esphome_core_version[CONF_LOCAL])
do_write = True do_write = True
if os.path.islink(dst_path): if islink(dst_path):
old_path = os.path.join(os.readlink(dst_path), lib_path) old_path = os.path.join(readlink(dst_path), lib_path)
if old_path != lib_path: if old_path != lib_path:
os.unlink(dst_path) unlink(dst_path)
else: else:
do_write = False do_write = False
if do_write: if do_write:
@ -231,8 +233,8 @@ def symlink_esphome_core_version(esphome_core_version):
symlink(src_path, dst_path) symlink(src_path, dst_path)
else: else:
# Remove symlink when changing back from local version # Remove symlink when changing back from local version
if os.path.islink(dst_path): if islink(dst_path):
os.unlink(dst_path) unlink(dst_path)
def format_ini(data): def format_ini(data):
@ -288,7 +290,7 @@ def gather_lib_deps():
lib_deps.add('AsyncTCP@1.0.1') lib_deps.add('AsyncTCP@1.0.1')
lib_deps.add('ESPmDNS') lib_deps.add('ESPmDNS')
elif CORE.is_esp8266: elif CORE.is_esp8266:
lib_deps.add('ESPAsyncTCP@1.1.3') lib_deps.add('ESPAsyncTCP@1.2.0')
lib_deps.add('ESP8266mDNS') lib_deps.add('ESP8266mDNS')
# avoid changing build flags order # avoid changing build flags order
@ -341,13 +343,14 @@ def gather_build_flags():
'-DUSE_WIFI_SIGNAL_SENSOR', '-DUSE_WIFI_SIGNAL_SENSOR',
} }
if CORE.is_esp8266 and CORE.board in ESP8266_FLASH_SIZES: if CORE.is_esp8266 and CORE.board in ESP8266_FLASH_SIZES and \
CORE.arduino_version != ARDUINO_VERSION_ESP8266_2_3_0:
flash_size = ESP8266_FLASH_SIZES[CORE.board] flash_size = ESP8266_FLASH_SIZES[CORE.board]
ld_scripts = ESP8266_LD_SCRIPTS[flash_size] ld_scripts = ESP8266_LD_SCRIPTS[flash_size]
ld_script = None ld_script = None
if CORE.arduino_version in ('espressif8266@1.8.0', 'espressif8266@1.7.3', if CORE.arduino_version in ('espressif8266@1.8.0', 'espressif8266@1.7.3',
'espressif8266@1.6.0', 'espressif8266@1.5.0'): 'espressif8266@1.6.0'):
ld_script = ld_scripts[0] ld_script = ld_scripts[0]
elif CORE.arduino_version in (ARDUINO_VERSION_ESP8266_DEV, ARDUINO_VERSION_ESP8266_2_5_0): elif CORE.arduino_version in (ARDUINO_VERSION_ESP8266_DEV, ARDUINO_VERSION_ESP8266_2_5_0):
ld_script = ld_scripts[1] ld_script = ld_scripts[1]