esphome/esphome/wizard.py

280 lines
9.9 KiB
Python
Raw Normal View History

2018-04-07 01:23:03 +02:00
from __future__ import print_function
import codecs
import os
import unicodedata
import voluptuous as vol
import esphome.config_validation as cv
from esphome.helpers import color, get_bool_env
# pylint: disable=anomalous-backslash-in-string
from esphome.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS
from esphome.py_compat import safe_input, text_type
from esphome.storage_json import StorageJSON, ext_storage_path
from esphome.util import safe_print
2018-09-23 18:58:41 +02:00
CORE_BIG = r""" _____ ____ _____ ______
2018-04-07 01:23:03 +02:00
/ ____/ __ \| __ \| ____|
| | | | | | |__) | |__
| | | | | | _ /| __|
| |___| |__| | | \ \| |____
2018-04-07 01:23:03 +02:00
\_____\____/|_| \_\______|
"""
ESP_BIG = r""" ______ _____ _____
| ____|/ ____| __ \\
2018-04-07 01:23:03 +02:00
| |__ | (___ | |__) |
| __| \___ \| ___/
| |____ ____) | |
|______|_____/|_|
2018-04-07 01:23:03 +02:00
"""
WIFI_BIG = r""" __ ___ ______ _
2018-04-07 01:23:03 +02:00
\ \ / (_) ____(_)
\ \ /\ / / _| |__ _
2018-04-07 01:23:03 +02:00
\ \/ \/ / | | __| | |
\ /\ / | | | | |
\/ \/ |_|_| |_|
"""
OTA_BIG = r""" ____ _______
/ __ \__ __|/\\
| | | | | | / \\
| | | | | | / /\ \\
| |__| | | |/ ____ \\
2018-04-07 01:23:03 +02:00
\____/ |_/_/ \_\\
"""
BASE_CONFIG = u"""esphome:
2018-04-07 01:23:03 +02:00
name: {name}
platform: {platform}
board: {board}
wifi:
ssid: "{ssid}"
password: "{psk}"
2018-04-07 01:23:03 +02:00
# Enable logging
logger:
# Enable Home Assistant API
api:
2018-04-07 01:23:03 +02:00
"""
def sanitize_double_quotes(value):
return value.replace('\\', '\\\\').replace('"', '\\"')
def wizard_file(**kwargs):
config = BASE_CONFIG.format(**kwargs)
if kwargs['password']:
config += u' password: "{0}"\n\nota:\n password: "{0}"\n'.format(kwargs['password'])
else:
config += u"\nota:\n"
return config
[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234) * Implement custom sensor platform * Update * Ethernet * Lint * Fix * Login page * Rename cookie secret * Update manifest * Update cookie check logic * Favicon * Fix * Favicon manifest * Fix * Fix * Fix * Use hostname * Message * Temporary commit for screenshot * Automatic board selection * Undo temporary commit * Update esphomeyaml-edge * In-dashboard editing and hosting files locally * Update esphomeyaml-edge * Better ANSI color escaping * Message * Lint * Download Efficiency * Fix gitlab * Fix * Rename extra_libraries to libraries * Add example * Update README.md * Update README.md * Update README.md * HassIO -> Hass.io * Updates * Add update available notice * Update * Fix substitutions * Better error message * Re-do dashboard ANSI colors * Only include FastLED if user says so * Autoscroll logs * Remove old checks * Use safer RedirectText * Improvements * Fix * Use enviornment variable * Use http://hassio/host/info * Fix conditions * Update platformio versions * Revert "Use enviornment variable" This reverts commit 7f038eb5d26df72f76ea9ae76774e2cec1fd7f59. * Fix * README update * Temp * Better invalid config messages * Platformio debug * Improve error messages * Debug * Remove debug * Multi Conf * Update * Better paths * Remove unused * Fixes * Lint * lib_ignore * Try fix platformio colors * Fix dashboard scrolling * Revert * Lint * Revert
2018-12-05 21:22:06 +01:00
def wizard_write(path, **kwargs):
name = kwargs['name']
board = kwargs['board']
kwargs['ssid'] = sanitize_double_quotes(kwargs['ssid'])
kwargs['psk'] = sanitize_double_quotes(kwargs['psk'])
kwargs['password'] = sanitize_double_quotes(kwargs['password'])
[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234) * Implement custom sensor platform * Update * Ethernet * Lint * Fix * Login page * Rename cookie secret * Update manifest * Update cookie check logic * Favicon * Fix * Favicon manifest * Fix * Fix * Fix * Use hostname * Message * Temporary commit for screenshot * Automatic board selection * Undo temporary commit * Update esphomeyaml-edge * In-dashboard editing and hosting files locally * Update esphomeyaml-edge * Better ANSI color escaping * Message * Lint * Download Efficiency * Fix gitlab * Fix * Rename extra_libraries to libraries * Add example * Update README.md * Update README.md * Update README.md * HassIO -> Hass.io * Updates * Add update available notice * Update * Fix substitutions * Better error message * Re-do dashboard ANSI colors * Only include FastLED if user says so * Autoscroll logs * Remove old checks * Use safer RedirectText * Improvements * Fix * Use enviornment variable * Use http://hassio/host/info * Fix conditions * Update platformio versions * Revert "Use enviornment variable" This reverts commit 7f038eb5d26df72f76ea9ae76774e2cec1fd7f59. * Fix * README update * Temp * Better invalid config messages * Platformio debug * Improve error messages * Debug * Remove debug * Multi Conf * Update * Better paths * Remove unused * Fixes * Lint * lib_ignore * Try fix platformio colors * Fix dashboard scrolling * Revert * Lint * Revert
2018-12-05 21:22:06 +01:00
if 'platform' not in kwargs:
kwargs['platform'] = 'ESP8266' if board in ESP8266_BOARD_PINS else 'ESP32'
platform = kwargs['platform']
with codecs.open(path, 'w', 'utf-8') as f_handle:
[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234) * Implement custom sensor platform * Update * Ethernet * Lint * Fix * Login page * Rename cookie secret * Update manifest * Update cookie check logic * Favicon * Fix * Favicon manifest * Fix * Fix * Fix * Use hostname * Message * Temporary commit for screenshot * Automatic board selection * Undo temporary commit * Update esphomeyaml-edge * In-dashboard editing and hosting files locally * Update esphomeyaml-edge * Better ANSI color escaping * Message * Lint * Download Efficiency * Fix gitlab * Fix * Rename extra_libraries to libraries * Add example * Update README.md * Update README.md * Update README.md * HassIO -> Hass.io * Updates * Add update available notice * Update * Fix substitutions * Better error message * Re-do dashboard ANSI colors * Only include FastLED if user says so * Autoscroll logs * Remove old checks * Use safer RedirectText * Improvements * Fix * Use enviornment variable * Use http://hassio/host/info * Fix conditions * Update platformio versions * Revert "Use enviornment variable" This reverts commit 7f038eb5d26df72f76ea9ae76774e2cec1fd7f59. * Fix * README update * Temp * Better invalid config messages * Platformio debug * Improve error messages * Debug * Remove debug * Multi Conf * Update * Better paths * Remove unused * Fixes * Lint * lib_ignore * Try fix platformio colors * Fix dashboard scrolling * Revert * Lint * Revert
2018-12-05 21:22:06 +01:00
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))
storage.save(storage_path)
if get_bool_env('ESPHOME_QUICKWIZARD'):
def sleep(time):
pass
else:
from time import sleep
2018-04-07 01:23:03 +02:00
def safe_print_step(step, big):
safe_print()
safe_print()
safe_print("============= STEP {} =============".format(step))
safe_print(big)
safe_print("===================================")
2018-04-07 01:23:03 +02:00
sleep(0.25)
def default_input(text, default):
safe_print()
safe_print(u"Press ENTER for default ({})".format(default))
return safe_input(text.format(default)) or default
2018-04-07 01:23:03 +02:00
# From https://stackoverflow.com/a/518232/8924614
def strip_accents(string):
return u''.join(c for c in unicodedata.normalize('NFD', text_type(string))
2018-04-07 01:23:03 +02:00
if unicodedata.category(c) != 'Mn')
def wizard(path):
if not path.endswith('.yaml') and not path.endswith('.yml'):
safe_print(u"Please make your configuration file {} have the extension .yaml or .yml"
u"".format(color('cyan', path)))
2018-04-07 01:23:03 +02:00
return 1
if os.path.exists(path):
safe_print(u"Uh oh, it seems like {} already exists, please delete that file first "
u"or chose another configuration file.".format(color('cyan', path)))
2018-04-07 01:23:03 +02:00
return 1
safe_print("Hi there!")
2018-04-07 01:23:03 +02:00
sleep(1.5)
safe_print("I'm the wizard of ESPHome :)")
2018-04-07 01:23:03 +02:00
sleep(1.25)
safe_print("And I'm here to help you get started with ESPHome.")
2018-04-07 01:23:03 +02:00
sleep(2.0)
safe_print("In 4 steps I'm going to guide you through creating a basic "
"configuration file for your custom ESP8266/ESP32 firmware. Yay!")
2018-04-07 01:23:03 +02:00
sleep(3.0)
safe_print()
safe_print_step(1, CORE_BIG)
safe_print("First up, please choose a " + color('green', 'name') + " for your node.")
safe_print("It should be a unique name that can be used to identify the device later.")
2018-04-07 01:23:03 +02:00
sleep(1)
safe_print("For example, I like calling the node in my living room {}.".format(
2018-04-07 01:23:03 +02:00
color('bold_white', "livingroom")))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(1)
name = safe_input(color("bold_white", "(name): "))
2018-04-07 01:23:03 +02:00
while True:
try:
name = cv.valid_name(name)
break
except vol.Invalid:
safe_print(color("red", u"Oh noes, \"{}\" isn't a valid name. Names can only include "
u"numbers, letters and underscores.".format(name)))
2018-04-07 01:23:03 +02:00
name = strip_accents(name).replace(' ', '_')
name = u''.join(c for c in name if c in cv.ALLOWED_NAME_CHARS)
safe_print(u"Shall I use \"{}\" as the name instead?".format(color('cyan', name)))
2018-04-07 01:23:03 +02:00
sleep(0.5)
name = default_input(u"(name [{}]): ", name)
2018-04-07 01:23:03 +02:00
safe_print(u"Great! Your node is now called \"{}\".".format(color('cyan', name)))
2018-04-07 01:23:03 +02:00
sleep(1)
safe_print_step(2, ESP_BIG)
safe_print("Now I'd like to know what microcontroller you're using so that I can compile "
"firmwares for it.")
safe_print("Are you using an " + color('green', 'ESP32') + " or " +
color('green', 'ESP8266') + " platform? (Choose ESP8266 for Sonoff devices)")
2018-04-07 01:23:03 +02:00
while True:
sleep(0.5)
safe_print()
safe_print("Please enter either ESP32 or ESP8266.")
platform = safe_input(color("bold_white", "(ESP32/ESP8266): "))
2018-04-07 01:23:03 +02:00
try:
🏗 Merge C++ into python codebase (#504) ## Description: Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97 Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍 Progress: - Core support (file copy etc): 80% - Base Abstractions (light, switch): ~50% - Integrations: ~10% - Working? Yes, (but only with ported components). Other refactors: - Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`) - Rework coroutine syntax - Move from `component/platform.py` to `domain/component.py` structure as with HA - Move all defaults out of C++ and into config validation. - Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration. - Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit. Future work: - Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block - Enable loading from `custom_components` folder. **Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97 **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
2019-04-17 12:06:00 +02:00
platform = vol.All(vol.Upper, vol.Any('ESP32', 'ESP8266'))(platform)
2018-04-07 01:23:03 +02:00
break
except vol.Invalid:
safe_print(u"Unfortunately, I can't find an espressif microcontroller called "
u"\"{}\". Please try again.".format(platform))
safe_print(u"Thanks! You've chosen {} as your platform.".format(color('cyan', platform)))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(1)
🏗 Merge C++ into python codebase (#504) ## Description: Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97 Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍 Progress: - Core support (file copy etc): 80% - Base Abstractions (light, switch): ~50% - Integrations: ~10% - Working? Yes, (but only with ported components). Other refactors: - Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`) - Rework coroutine syntax - Move from `component/platform.py` to `domain/component.py` structure as with HA - Move all defaults out of C++ and into config validation. - Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration. - Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit. Future work: - Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block - Enable loading from `custom_components` folder. **Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97 **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
2019-04-17 12:06:00 +02:00
if platform == 'ESP32':
2018-04-07 01:23:03 +02:00
board_link = 'http://docs.platformio.org/en/latest/platforms/espressif32.html#boards'
else:
board_link = 'http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards'
safe_print("Next, I need to know what " + color('green', 'board') + " you're using.")
2018-04-07 01:23:03 +02:00
sleep(0.5)
safe_print("Please go to {} and choose a board.".format(color('green', board_link)))
🏗 Merge C++ into python codebase (#504) ## Description: Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97 Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍 Progress: - Core support (file copy etc): 80% - Base Abstractions (light, switch): ~50% - Integrations: ~10% - Working? Yes, (but only with ported components). Other refactors: - Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`) - Rework coroutine syntax - Move from `component/platform.py` to `domain/component.py` structure as with HA - Move all defaults out of C++ and into config validation. - Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration. - Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit. Future work: - Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block - Enable loading from `custom_components` folder. **Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97 **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
2019-04-17 12:06:00 +02:00
if platform == 'ESP32':
safe_print("(Type " + color('green', 'esp01_1m') + " for Sonoff devices)")
safe_print()
2018-04-07 01:23:03 +02:00
# Don't sleep because user needs to copy link
🏗 Merge C++ into python codebase (#504) ## Description: Move esphome-core codebase into esphome (and a bunch of other refactors). See https://github.com/esphome/feature-requests/issues/97 Yes this is a shit ton of work and no there's no way to automate it :( But it will be worth it 👍 Progress: - Core support (file copy etc): 80% - Base Abstractions (light, switch): ~50% - Integrations: ~10% - Working? Yes, (but only with ported components). Other refactors: - Moves all codegen related stuff into a single class: `esphome.codegen` (imported as `cg`) - Rework coroutine syntax - Move from `component/platform.py` to `domain/component.py` structure as with HA - Move all defaults out of C++ and into config validation. - Remove `make_...` helpers from Application class. Reason: Merge conflicts with every single new integration. - Pointer Variables are stored globally instead of locally in setup(). Reason: stack size limit. Future work: - Rework const.py - Move all `CONF_...` into a conf class (usage `conf.UPDATE_INTERVAL` vs `CONF_UPDATE_INTERVAL`). Reason: Less convoluted import block - Enable loading from `custom_components` folder. **Related issue (if applicable):** https://github.com/esphome/feature-requests/issues/97 **Pull request in [esphome-docs](https://github.com/esphome/esphome-docs) with documentation (if applicable):** esphome/esphome-docs#<esphome-docs PR number goes here> ## Checklist: - [ ] The code change is tested and works locally. - [ ] Tests have been added to verify that the new code works (under `tests/` folder). If user exposed functionality or configuration variables are added/changed: - [ ] Documentation added/updated in [esphomedocs](https://github.com/OttoWinter/esphomedocs).
2019-04-17 12:06:00 +02:00
if platform == 'ESP32':
safe_print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s')))
2018-09-23 18:58:41 +02:00
boards = list(ESP32_BOARD_PINS.keys())
2018-04-07 01:23:03 +02:00
else:
safe_print("For example \"{}\".".format(color("bold_white", 'nodemcuv2')))
2018-09-23 18:58:41 +02:00
boards = list(ESP8266_BOARD_PINS.keys())
safe_print("Options: {}".format(', '.join(boards)))
2018-04-07 01:23:03 +02:00
while True:
board = safe_input(color("bold_white", "(board): "))
2018-04-07 01:23:03 +02:00
try:
board = vol.All(vol.Lower, vol.Any(*boards))(board)
break
except vol.Invalid:
safe_print(color('red', "Sorry, I don't think the board \"{}\" exists."))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(0.25)
safe_print()
2018-04-07 01:23:03 +02:00
safe_print(u"Way to go! You've chosen {} as your board.".format(color('cyan', board)))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(1)
safe_print_step(3, WIFI_BIG)
safe_print("In this step, I'm going to create the configuration for "
"WiFi.")
safe_print()
2018-04-07 01:23:03 +02:00
sleep(1)
safe_print("First, what's the " + color('green', 'SSID') +
u" (the name) of the WiFi network {} I should connect to?".format(name))
2018-04-07 01:23:03 +02:00
sleep(1.5)
safe_print("For example \"{}\".".format(color('bold_white', "Abraham Linksys")))
2018-04-07 01:23:03 +02:00
while True:
ssid = safe_input(color('bold_white', "(ssid): "))
2018-04-07 01:23:03 +02:00
try:
ssid = cv.ssid(ssid)
break
except vol.Invalid:
safe_print(color('red', u"Unfortunately, \"{}\" doesn't seem to be a valid SSID. "
u"Please try again.".format(ssid)))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(1)
safe_print(u"Thank you very much! You've just chosen \"{}\" as your SSID."
u"".format(color('cyan', ssid)))
safe_print()
2018-04-07 01:23:03 +02:00
sleep(0.75)
safe_print("Now please state the " + color('green', 'password') +
" of the WiFi network so that I can connect to it (Leave empty for no password)")
safe_print()
safe_print("For example \"{}\"".format(color('bold_white', 'PASSWORD42')))
2018-04-07 01:23:03 +02:00
sleep(0.5)
psk = safe_input(color('bold_white', '(PSK): '))
safe_print("Perfect! WiFi is now set up (you can create static IPs and so on later).")
2018-04-07 01:23:03 +02:00
sleep(1.5)
safe_print_step(4, OTA_BIG)
safe_print("Almost there! ESPHome can automatically upload custom firmwares over WiFi "
"(over the air) and integrates into Home Assistant with a native API.")
safe_print("This can be insecure if you do not trust the WiFi network. Do you want to set "
"a " + color('green', 'password') + " for connecting to this ESP?")
safe_print()
2018-04-07 01:23:03 +02:00
sleep(0.25)
safe_print("Press ENTER for no password")
password = safe_input(color('bold_white', '(password): '))
2018-04-07 01:23:03 +02:00
[Huge] Util Refactor, Dashboard Improvements, Hass.io Auth API, Better Validation Errors, Conditions, Custom Platforms, Substitutions (#234) * Implement custom sensor platform * Update * Ethernet * Lint * Fix * Login page * Rename cookie secret * Update manifest * Update cookie check logic * Favicon * Fix * Favicon manifest * Fix * Fix * Fix * Use hostname * Message * Temporary commit for screenshot * Automatic board selection * Undo temporary commit * Update esphomeyaml-edge * In-dashboard editing and hosting files locally * Update esphomeyaml-edge * Better ANSI color escaping * Message * Lint * Download Efficiency * Fix gitlab * Fix * Rename extra_libraries to libraries * Add example * Update README.md * Update README.md * Update README.md * HassIO -> Hass.io * Updates * Add update available notice * Update * Fix substitutions * Better error message * Re-do dashboard ANSI colors * Only include FastLED if user says so * Autoscroll logs * Remove old checks * Use safer RedirectText * Improvements * Fix * Use enviornment variable * Use http://hassio/host/info * Fix conditions * Update platformio versions * Revert "Use enviornment variable" This reverts commit 7f038eb5d26df72f76ea9ae76774e2cec1fd7f59. * Fix * README update * Temp * Better invalid config messages * Platformio debug * Improve error messages * Debug * Remove debug * Multi Conf * Update * Better paths * Remove unused * Fixes * Lint * lib_ignore * Try fix platformio colors * Fix dashboard scrolling * Revert * Lint * Revert
2018-12-05 21:22:06 +01:00
wizard_write(path=path, name=name, platform=platform, board=board,
ssid=ssid, psk=psk, password=password)
2018-04-07 01:23:03 +02:00
safe_print()
safe_print(color('cyan', "DONE! I've now written a new configuration file to ") +
color('bold_cyan', path))
safe_print()
safe_print("Next steps:")
safe_print(" > Check your Home Assistant \"integrations\" screen. If all goes well, you "
"should see your ESP being discovered automatically.")
safe_print(" > Then follow the rest of the getting started guide:")
safe_print(" > https://esphome.io/guides/getting_started_command_line.html")
2018-04-07 01:23:03 +02:00
return 0