mirror of
https://github.com/esphome/esphome.git
synced 2025-11-15 14:25:45 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac0b095941 | ||
|
|
cda9bad233 | ||
|
|
41db8a1264 | ||
|
|
e7e785fd60 | ||
|
|
300d3a1f46 | ||
|
|
356554c08d | ||
|
|
ced28ad006 | ||
|
|
6ccab2bef9 | ||
|
|
475aa4879c | ||
|
|
4452473735 | ||
|
|
948adfd28c | ||
|
|
aebbd7673b | ||
|
|
3baaf6b7c4 | ||
|
|
4a14221e2b | ||
|
|
114ebf9fe1 |
@@ -41,11 +41,11 @@ stages:
|
||||
|
||||
- |
|
||||
if [[ "${IS_HASSIO}" == "YES" ]]; then
|
||||
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.3.0
|
||||
BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3
|
||||
BUILD_TO=esphome/esphome-hassio-${BUILD_ARCH}
|
||||
DOCKERFILE=docker/Dockerfile.hassio
|
||||
else
|
||||
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.3.0
|
||||
BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3
|
||||
if [[ "${BUILD_ARCH}" == "amd64" ]]; then
|
||||
BUILD_TO=esphome/esphome
|
||||
else
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG BUILD_FROM=esphome/esphome-base-amd64:1.3.0
|
||||
ARG BUILD_FROM=esphome/esphome-base-amd64:1.4.3
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
COPY . .
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.3.0
|
||||
ARG BUILD_FROM=esphome/esphome-hassio-base-amd64:1.4.3
|
||||
FROM ${BUILD_FROM}
|
||||
|
||||
# Copy root filesystem
|
||||
|
||||
@@ -16,11 +16,11 @@ echo "PWD: $PWD"
|
||||
|
||||
if [[ ${IS_HASSIO} = "YES" ]]; then
|
||||
docker build \
|
||||
--build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.3.0" \
|
||||
--build-arg "BUILD_FROM=esphome/esphome-hassio-base-${BUILD_ARCH}:1.4.3" \
|
||||
--build-arg "BUILD_VERSION=${CACHE_TAG}" \
|
||||
-t "${IMAGE_NAME}" -f ../docker/Dockerfile.hassio ..
|
||||
else
|
||||
docker build \
|
||||
--build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.3.0" \
|
||||
--build-arg "BUILD_FROM=esphome/esphome-base-${BUILD_ARCH}:1.4.3" \
|
||||
-t "${IMAGE_NAME}" -f ../docker/Dockerfile ..
|
||||
fi
|
||||
|
||||
@@ -1,35 +1,41 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# This files check if all user configuration requirements are met
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
# Check SSL requirements, if enabled
|
||||
if hass.config.true 'ssl'; then
|
||||
if ! hass.config.has_value 'certfile'; then
|
||||
hass.die 'SSL is enabled, but no certfile was specified.'
|
||||
if bashio::config.true 'ssl'; then
|
||||
if ! bashio::config.has_value 'certfile'; then
|
||||
bashio::fatal 'SSL is enabled, but no certfile was specified.'
|
||||
bashio::exit.nok
|
||||
fi
|
||||
|
||||
if ! hass.config.has_value 'keyfile'; then
|
||||
hass.die 'SSL is enabled, but no keyfile was specified'
|
||||
if ! bashio::config.has_value 'keyfile'; then
|
||||
bashio::fatal 'SSL is enabled, but no keyfile was specified'
|
||||
bashio::exit.nok
|
||||
fi
|
||||
|
||||
if ! hass.file_exists "/ssl/$(hass.config.get 'certfile')"; then
|
||||
if ! hass.file_exists "/ssl/$(hass.config.get 'keyfile')"; then
|
||||
|
||||
certfile="/ssl/$(bashio::config 'certfile')"
|
||||
keyfile="/ssl/$(bashio::config 'keyfile')"
|
||||
|
||||
if ! bashio::fs.file_exists "${certfile}"; then
|
||||
if ! bashio::fs.file_exists "${keyfile}"; then
|
||||
# Both files are missing, let's print a friendlier error message
|
||||
text="You enabled encrypted connections using the \"ssl\": true option.
|
||||
However, the SSL files \"$(hass.config.get 'certfile')\" and \"$(hass.config.get 'keyfile')\"
|
||||
were not found. If you're using Hass.io on your local network and don't want
|
||||
to encrypt connections to the ESPHome dashboard, you can manually disable
|
||||
SSL by setting \"ssl\" to false."
|
||||
hass.die "${text}"
|
||||
bashio::log.fatal 'You enabled encrypted connections using the "ssl": true option.'
|
||||
bashio::log.fatal "However, the SSL files '${certfile}' and '${keyfile}'"
|
||||
bashio::log.fatal "were not found. If you're using Hass.io on your local network and don't want"
|
||||
bashio::log.fatal 'to encrypt connections to the ESPHome dashboard, you can manually disable'
|
||||
bashio::log.fatal 'SSL by setting "ssl" to false."'
|
||||
bashio::exit.nok
|
||||
fi
|
||||
hass.die 'The configured certfile is not found'
|
||||
bashio::log.fatal "The configured certfile '${certfile}' was not found."
|
||||
bashio::exit.nok
|
||||
fi
|
||||
|
||||
if ! hass.file_exists "/ssl/$(hass.config.get 'keyfile')"; then
|
||||
hass.die 'The configured keyfile is not found'
|
||||
if ! bashio::fs.file_exists "/ssl/$(bashio::config 'keyfile')"; then
|
||||
bashio::log.fatal "The configured keyfile '${keyfile}' was not found."
|
||||
bashio::exit.nok
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# Configures NGINX for use with ESPHome
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
declare certfile
|
||||
declare keyfile
|
||||
@@ -13,16 +11,16 @@ declare port
|
||||
mkdir -p /var/log/nginx
|
||||
|
||||
# Enable SSL
|
||||
if hass.config.true 'ssl'; then
|
||||
if bashio::config.true 'ssl'; then
|
||||
rm /etc/nginx/nginx.conf
|
||||
mv /etc/nginx/nginx-ssl.conf /etc/nginx/nginx.conf
|
||||
|
||||
certfile=$(hass.config.get 'certfile')
|
||||
keyfile=$(hass.config.get 'keyfile')
|
||||
certfile=$(bashio::config 'certfile')
|
||||
keyfile=$(bashio::config 'keyfile')
|
||||
|
||||
sed -i "s/%%certfile%%/${certfile}/g" /etc/nginx/nginx.conf
|
||||
sed -i "s/%%keyfile%%/${keyfile}/g" /etc/nginx/nginx.conf
|
||||
fi
|
||||
|
||||
port=$(hass.config.get 'port')
|
||||
port=$(bashio::config 'port')
|
||||
sed -i "s/%%port%%/${port}/g" /etc/nginx/nginx.conf
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# This files installs the user ESPHome version if specified
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
declare esphome_version
|
||||
|
||||
if hass.config.has_value 'esphome_version'; then
|
||||
esphome_version=$(hass.config.get 'esphome_version')
|
||||
pip2 install --no-cache-dir --no-binary :all: "https://github.com/esphome/esphome/archive/${esphome_version}.zip"
|
||||
if bashio::config.has_value 'esphome_version'; then
|
||||
esphome_version=$(bashio::config 'esphome_version')
|
||||
full_url="https://github.com/esphome/esphome/archive/${esphome_version}.zip"
|
||||
bashio::log.info "Installing esphome version '${esphome_version}' (${full_url})..."
|
||||
pip2 install --no-cache-dir --no-binary :all: "${full_url}" \
|
||||
|| bashio::exit.nok "Failed installing esphome pinned version."
|
||||
fi
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# This files migrates the esphome config directory from the old path
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
if [[ ! -d /config/esphome && -d /config/esphomeyaml ]]; then
|
||||
echo "Moving config directory from /config/esphomeyaml to /config/esphome"
|
||||
|
||||
@@ -1,28 +1,26 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# Runs the ESPHome dashboard
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
export ESPHOME_IS_HASSIO=true
|
||||
|
||||
if hass.config.true 'leave_front_door_open'; then
|
||||
if bashio::config.true 'leave_front_door_open'; then
|
||||
export DISABLE_HA_AUTHENTICATION=true
|
||||
fi
|
||||
|
||||
if hass.config.true 'streamer_mode'; then
|
||||
if bashio::config.true 'streamer_mode'; then
|
||||
export ESPHOME_STREAMER_MODE=true
|
||||
fi
|
||||
|
||||
if hass.config.true 'status_use_ping'; then
|
||||
if bashio::config.true 'status_use_ping'; then
|
||||
export ESPHOME_DASHBOARD_USE_PING=true
|
||||
fi
|
||||
|
||||
if hass.config.has_value 'relative_url'; then
|
||||
export ESPHOME_DASHBOARD_RELATIVE_URL=$(hass.config.get 'relative_url')
|
||||
if bashio::config.has_value 'relative_url'; then
|
||||
export ESPHOME_DASHBOARD_RELATIVE_URL=$(bashio::config 'relative_url')
|
||||
fi
|
||||
|
||||
hass.log.info "Starting ESPHome dashboard..."
|
||||
bashio::log.info "Starting ESPHome dashboard..."
|
||||
exec esphome /config/esphome dashboard --socket /var/run/esphome.sock --hassio
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
#!/usr/bin/with-contenv bash
|
||||
#!/usr/bin/with-contenv bashio
|
||||
# ==============================================================================
|
||||
# Community Hass.io Add-ons: ESPHome
|
||||
# Runs the NGINX proxy
|
||||
# ==============================================================================
|
||||
# shellcheck disable=SC1091
|
||||
source /usr/lib/hassio-addons/base.sh
|
||||
|
||||
hass.log.info "Starting NGINX..."
|
||||
bashio::log.info "Starting NGINX..."
|
||||
exec nginx -g "daemon off;"
|
||||
|
||||
@@ -86,7 +86,7 @@ def lib_deps(config):
|
||||
if CORE.is_esp32:
|
||||
return 'AsyncTCP@1.0.3'
|
||||
if CORE.is_esp8266:
|
||||
return 'ESPAsyncTCP@1.1.3'
|
||||
return 'ESPAsyncTCP@1.2.0'
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ from esphome.cpp_helpers import setup_component
|
||||
from esphome.cpp_types import App, Component, esphome_ns
|
||||
|
||||
ESP_PLATFORMS = [ESP_PLATFORM_ESP32]
|
||||
CONFLICTS_WITH = ['esp32_ble_tracker']
|
||||
|
||||
ESP32BLEBeacon = esphome_ns.class_('ESP32BLEBeacon', Component)
|
||||
|
||||
|
||||
@@ -64,11 +64,11 @@ CONFIG_SCHEMA = cv.Schema({
|
||||
vol.Required(CONF_VSYNC_PIN): pins.input_pin,
|
||||
vol.Required(CONF_HREF_PIN): pins.input_pin,
|
||||
vol.Required(CONF_PIXEL_CLOCK_PIN): pins.input_pin,
|
||||
vol.Required(CONF_EXTERNAL_CLOCK): vol.Schema({
|
||||
vol.Required(CONF_EXTERNAL_CLOCK): cv.Schema({
|
||||
vol.Required(CONF_PIN): pins.output_pin,
|
||||
vol.Optional(CONF_FREQUENCY, default='20MHz'): vol.All(cv.frequency, vol.In([20e6, 10e6])),
|
||||
}),
|
||||
vol.Required(CONF_I2C_PINS): vol.Schema({
|
||||
vol.Required(CONF_I2C_PINS): cv.Schema({
|
||||
vol.Required(CONF_SDA): pins.output_pin,
|
||||
vol.Required(CONF_SCL): pins.output_pin,
|
||||
}),
|
||||
@@ -127,4 +127,4 @@ def to_code(config):
|
||||
add(cam.set_frame_size(FRAME_SIZES[config[CONF_RESOLUTION]]))
|
||||
|
||||
|
||||
BUILD_FLAGS = '-DUSE_ESP32_CAMERA'
|
||||
BUILD_FLAGS = ['-DUSE_ESP32_CAMERA', '-DBOARD_HAS_PSRAM']
|
||||
|
||||
@@ -63,7 +63,7 @@ def to_code(config):
|
||||
if CONF_MIN_VALUE in config:
|
||||
add(encoder.set_min_value(config[CONF_MIN_VALUE]))
|
||||
if CONF_MAX_VALUE in config:
|
||||
add(encoder.set_min_value(config[CONF_MAX_VALUE]))
|
||||
add(encoder.set_max_value(config[CONF_MAX_VALUE]))
|
||||
|
||||
sensor.setup_sensor(encoder, config)
|
||||
setup_component(encoder, config)
|
||||
|
||||
@@ -46,7 +46,7 @@ def setup_text_sensor_core_(text_sensor_var, config):
|
||||
trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs)
|
||||
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):
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
MAJOR_VERSION = 1
|
||||
MINOR_VERSION = 12
|
||||
PATCH_VERSION = '0b2'
|
||||
PATCH_VERSION = '2'
|
||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||
ESPHOME_CORE_VERSION = '1.12.0b2'
|
||||
ESPHOME_CORE_VERSION = '1.12.2'
|
||||
|
||||
ESP_PLATFORM_ESP32 = 'ESP32'
|
||||
ESP_PLATFORM_ESP8266 = 'ESP8266'
|
||||
@@ -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' \
|
||||
'/stage'
|
||||
ARDUINO_VERSION_ESP8266_2_5_0 = 'espressif8266@2.0.0'
|
||||
ARDUINO_VERSION_ESP8266_2_3_0 = 'espressif8266@1.5.0'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from collections import OrderedDict
|
||||
import math
|
||||
|
||||
from esphome.core import CORE, HexInt, Lambda, TimePeriod, TimePeriodMicroseconds, \
|
||||
TimePeriodMilliseconds, TimePeriodSeconds, TimePeriodMinutes
|
||||
@@ -260,6 +261,8 @@ class FloatLiteral(Literal):
|
||||
self.float_ = value
|
||||
|
||||
def __str__(self):
|
||||
if math.isnan(self.float_):
|
||||
return u"NAN"
|
||||
return u"{:f}f".format(self.float_)
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import tornado.websocket
|
||||
from esphome import const
|
||||
from esphome.__main__ import get_serial_ports
|
||||
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, \
|
||||
esphome_storage_path, ext_storage_path, trash_storage_path
|
||||
from esphome.util import shlex_quote
|
||||
@@ -223,8 +223,8 @@ class WizardRequestHandler(BaseHandler):
|
||||
def post(self):
|
||||
from esphome import wizard
|
||||
|
||||
kwargs = {k: ''.join(v) for k, v in self.request.arguments.items()}
|
||||
destination = os.path.join(CONFIG_DIR, kwargs['name'] + '.yaml')
|
||||
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'] + u'.yaml')
|
||||
wizard.wizard_write(path=destination, **kwargs)
|
||||
self.redirect('/?begin=True')
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ def perform_ota(sock, password, file_handle, filename):
|
||||
send_check(sock, cnonce, 'auth cnonce')
|
||||
|
||||
result_md5 = hashlib.md5()
|
||||
result_md5.update(password.encode())
|
||||
result_md5.update(password.encode('utf-8'))
|
||||
result_md5.update(nonce.encode())
|
||||
result_md5.update(cnonce.encode())
|
||||
result = result_md5.hexdigest()
|
||||
|
||||
@@ -140,16 +140,3 @@ def get_bool_env(var, default=False):
|
||||
|
||||
def 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()
|
||||
|
||||
@@ -69,3 +69,13 @@ def indexbytes(buf, i):
|
||||
return buf[i]
|
||||
else:
|
||||
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
164
esphome/symlink_ops.py
Normal 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)
|
||||
@@ -159,3 +159,7 @@ class _Schema(vol.Schema):
|
||||
return out
|
||||
|
||||
return validate_mapping
|
||||
|
||||
def extend(self, schema, required=None, extra=None):
|
||||
ret = vol.Schema.extend(self, schema, required=required, extra=extra)
|
||||
return _Schema(ret.schema, required=ret.required, extra=ret.extra)
|
||||
|
||||
@@ -79,7 +79,7 @@ def wizard_write(path, **kwargs):
|
||||
kwargs['platform'] = 'ESP8266' if board in ESP8266_BOARD_PINS else 'ESP32'
|
||||
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))
|
||||
storage = StorageJSON.from_wizard(name, name + '.local', platform, board)
|
||||
storage_path = ext_storage_path(os.path.dirname(path), os.path.basename(path))
|
||||
|
||||
@@ -10,10 +10,12 @@ import shutil
|
||||
from esphome.config import iter_components
|
||||
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, \
|
||||
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_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.py_compat import IS_PY3, string_types
|
||||
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:
|
||||
src_path = CORE.relative_path(esphome_core_version[CONF_LOCAL])
|
||||
do_write = True
|
||||
if os.path.islink(dst_path):
|
||||
old_path = os.path.join(os.readlink(dst_path), lib_path)
|
||||
if islink(dst_path):
|
||||
old_path = os.path.join(readlink(dst_path), lib_path)
|
||||
if old_path != lib_path:
|
||||
os.unlink(dst_path)
|
||||
unlink(dst_path)
|
||||
else:
|
||||
do_write = False
|
||||
if do_write:
|
||||
@@ -231,8 +233,8 @@ def symlink_esphome_core_version(esphome_core_version):
|
||||
symlink(src_path, dst_path)
|
||||
else:
|
||||
# Remove symlink when changing back from local version
|
||||
if os.path.islink(dst_path):
|
||||
os.unlink(dst_path)
|
||||
if islink(dst_path):
|
||||
unlink(dst_path)
|
||||
|
||||
|
||||
def format_ini(data):
|
||||
@@ -288,7 +290,7 @@ def gather_lib_deps():
|
||||
lib_deps.add('AsyncTCP@1.0.1')
|
||||
lib_deps.add('ESPmDNS')
|
||||
elif CORE.is_esp8266:
|
||||
lib_deps.add('ESPAsyncTCP@1.1.3')
|
||||
lib_deps.add('ESPAsyncTCP@1.2.0')
|
||||
lib_deps.add('ESP8266mDNS')
|
||||
|
||||
# avoid changing build flags order
|
||||
@@ -341,13 +343,14 @@ def gather_build_flags():
|
||||
'-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]
|
||||
ld_scripts = ESP8266_LD_SCRIPTS[flash_size]
|
||||
ld_script = None
|
||||
|
||||
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]
|
||||
elif CORE.arduino_version in (ARDUINO_VERSION_ESP8266_DEV, ARDUINO_VERSION_ESP8266_2_5_0):
|
||||
ld_script = ld_scripts[1]
|
||||
|
||||
@@ -328,7 +328,7 @@ def represent_odict(dump, tag, mapping, flow_style=None):
|
||||
|
||||
|
||||
def represent_secret(value):
|
||||
return yaml.ScalarNode(tag=u'!secret', value=_SECRET_VALUES[value])
|
||||
return yaml.ScalarNode(tag=u'!secret', value=_SECRET_VALUES[text_type(value)])
|
||||
|
||||
|
||||
def unicode_representer(_, uni):
|
||||
|
||||
@@ -173,6 +173,7 @@ sensor:
|
||||
- 40.0 -> 45.0
|
||||
- 100.0 -> 102.5
|
||||
- filter_out: 42.0
|
||||
- filter_out: nan
|
||||
- sliding_window_moving_average:
|
||||
window_size: 15
|
||||
send_every: 15
|
||||
|
||||
@@ -172,9 +172,9 @@ remote_receiver:
|
||||
esp32_ble_tracker:
|
||||
scan_interval: 300s
|
||||
|
||||
esp32_ble_beacon:
|
||||
type: iBeacon
|
||||
uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98'
|
||||
#esp32_ble_beacon:
|
||||
# type: iBeacon
|
||||
# uuid: 'c29ce823-e67a-4e71-bff2-abaa32e77a98'
|
||||
|
||||
status_led:
|
||||
pin: GPIO2
|
||||
|
||||
Reference in New Issue
Block a user