mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 07:03:55 +00:00 
			
		
		
		
	Better ANSI color escaping
This commit is contained in:
		| @@ -63,7 +63,7 @@ def choose_serial_port(config): | |||||||
|     return result[opt][0] |     return result[opt][0] | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_miniterm(config, port, escape=False): | def run_miniterm(config, port): | ||||||
|     import serial |     import serial | ||||||
|     if CONF_LOGGER not in config: |     if CONF_LOGGER not in config: | ||||||
|         _LOGGER.info("Logger is not enabled. Not starting UART logs.") |         _LOGGER.info("Logger is not enabled. Not starting UART logs.") | ||||||
| @@ -84,7 +84,7 @@ def run_miniterm(config, port, escape=False): | |||||||
|             line = raw.replace('\r', '').replace('\n', '') |             line = raw.replace('\r', '').replace('\n', '') | ||||||
|             time = datetime.now().time().strftime('[%H:%M:%S]') |             time = datetime.now().time().strftime('[%H:%M:%S]') | ||||||
|             message = time + line |             message = time + line | ||||||
|             if escape: |             if core.FROM_DASHBOARD: | ||||||
|                 message = message.replace('\033', '\\033') |                 message = message.replace('\033', '\\033') | ||||||
|             safe_print(message) |             safe_print(message) | ||||||
|  |  | ||||||
| @@ -152,7 +152,7 @@ def upload_program(config, args, port): | |||||||
|     # if upload is to a serial port use platformio, otherwise assume ota |     # if upload is to a serial port use platformio, otherwise assume ota | ||||||
|     serial_port = port.startswith('/') or port.startswith('COM') |     serial_port = port.startswith('/') or port.startswith('COM') | ||||||
|     if port != 'OTA' and serial_port: |     if port != 'OTA' and serial_port: | ||||||
|         if CORE.is_esp8266 and args.use_esptoolpy: |         if CORE.is_esp8266 and args.dashboard: | ||||||
|             return upload_using_esptool(config, port) |             return upload_using_esptool(config, port) | ||||||
|         return platformio_api.run_upload(config, args.verbose, port) |         return platformio_api.run_upload(config, args.verbose, port) | ||||||
|  |  | ||||||
| @@ -187,13 +187,12 @@ def upload_program(config, args, port): | |||||||
|                                   CORE.firmware_bin) |                                   CORE.firmware_bin) | ||||||
|  |  | ||||||
|  |  | ||||||
| def show_logs(config, args, port, escape=False): | def show_logs(config, args, port): | ||||||
|     serial_port = port.startswith('/') or port.startswith('COM') |     serial_port = port.startswith('/') or port.startswith('COM') | ||||||
|     if port != 'OTA' and serial_port: |     if port != 'OTA' and serial_port: | ||||||
|         run_miniterm(config, port, escape=escape) |         run_miniterm(config, port) | ||||||
|         return 0 |         return 0 | ||||||
|     return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id, |     return mqtt.show_logs(config, args.topic, args.username, args.password, args.client_id) | ||||||
|                           escape=escape) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def clean_mqtt(config, args): | def clean_mqtt(config, args): | ||||||
| @@ -282,7 +281,7 @@ def command_upload(args, config): | |||||||
|  |  | ||||||
| def command_logs(args, config): | def command_logs(args, config): | ||||||
|     port = args.serial_port or choose_serial_port(config) |     port = args.serial_port or choose_serial_port(config) | ||||||
|     return show_logs(config, args, port, escape=args.escape) |     return show_logs(config, args, port) | ||||||
|  |  | ||||||
|  |  | ||||||
| def command_run(args, config): | def command_run(args, config): | ||||||
| @@ -300,7 +299,7 @@ def command_run(args, config): | |||||||
|     _LOGGER.info(u"Successfully uploaded program.") |     _LOGGER.info(u"Successfully uploaded program.") | ||||||
|     if args.no_logs: |     if args.no_logs: | ||||||
|         return 0 |         return 0 | ||||||
|     return show_logs(config, args, port, escape=args.escape) |     return show_logs(config, args, port) | ||||||
|  |  | ||||||
|  |  | ||||||
| def command_clean_mqtt(args, config): | def command_clean_mqtt(args, config): | ||||||
| @@ -381,21 +380,24 @@ def parse_args(argv): | |||||||
|  |  | ||||||
|     subparsers = parser.add_subparsers(help='Commands', dest='command') |     subparsers = parser.add_subparsers(help='Commands', dest='command') | ||||||
|     subparsers.required = True |     subparsers.required = True | ||||||
|     subparsers.add_parser('config', help='Validate the configuration and spit it out.') |     config = subparsers.add_parser('config', help='Validate the configuration and spit it out.') | ||||||
|  |     config.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|  |                         action='store_true') | ||||||
|  |  | ||||||
|     parser_compile = subparsers.add_parser('compile', |     parser_compile = subparsers.add_parser('compile', | ||||||
|                                            help='Read the configuration and compile a program.') |                                            help='Read the configuration and compile a program.') | ||||||
|     parser_compile.add_argument('--only-generate', |     parser_compile.add_argument('--only-generate', | ||||||
|                                 help="Only generate source code, do not compile.", |                                 help="Only generate source code, do not compile.", | ||||||
|                                 action='store_true') |                                 action='store_true') | ||||||
|  |     parser_compile.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|  |                                 action='store_true') | ||||||
|  |  | ||||||
|     parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' |     parser_upload = subparsers.add_parser('upload', help='Validate the configuration ' | ||||||
|                                                          'and upload the latest binary.') |                                                          'and upload the latest binary.') | ||||||
|     parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. " |     parser_upload.add_argument('--upload-port', help="Manually specify the upload port to use. " | ||||||
|                                                      "For example /dev/cu.SLAB_USBtoUART.") |                                                      "For example /dev/cu.SLAB_USBtoUART.") | ||||||
|     parser_upload.add_argument('--host-port', help="Specify the host port.", type=int) |     parser_upload.add_argument('--host-port', help="Specify the host port.", type=int) | ||||||
|     parser_upload.add_argument('--use-esptoolpy', |     parser_upload.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|                                help="Use esptool.py for the uploading (only for ESP8266)", |  | ||||||
|                                action='store_true') |                                action='store_true') | ||||||
|  |  | ||||||
|     parser_logs = subparsers.add_parser('logs', help='Validate the configuration ' |     parser_logs = subparsers.add_parser('logs', help='Validate the configuration ' | ||||||
| @@ -406,7 +408,7 @@ def parse_args(argv): | |||||||
|     parser_logs.add_argument('--client-id', help='Manually set the client id.') |     parser_logs.add_argument('--client-id', help='Manually set the client id.') | ||||||
|     parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use" |     parser_logs.add_argument('--serial-port', help="Manually specify a serial port to use" | ||||||
|                                                    "For example /dev/cu.SLAB_USBtoUART.") |                                                    "For example /dev/cu.SLAB_USBtoUART.") | ||||||
|     parser_logs.add_argument('--escape', help="Escape ANSI color codes for running in dashboard", |     parser_logs.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|                              action='store_true') |                              action='store_true') | ||||||
|  |  | ||||||
|     parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, ' |     parser_run = subparsers.add_parser('run', help='Validate the configuration, create a binary, ' | ||||||
| @@ -420,10 +422,7 @@ def parse_args(argv): | |||||||
|     parser_run.add_argument('--username', help='Manually set the MQTT username for logs.') |     parser_run.add_argument('--username', help='Manually set the MQTT username for logs.') | ||||||
|     parser_run.add_argument('--password', help='Manually set the MQTT password for logs.') |     parser_run.add_argument('--password', help='Manually set the MQTT password for logs.') | ||||||
|     parser_run.add_argument('--client-id', help='Manually set the client id for logs.') |     parser_run.add_argument('--client-id', help='Manually set the client id for logs.') | ||||||
|     parser_run.add_argument('--escape', help="Escape ANSI color codes for running in dashboard", |     parser_run.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|                             action='store_true') |  | ||||||
|     parser_run.add_argument('--use-esptoolpy', |  | ||||||
|                             help="Use esptool.py for the uploading (only for ESP8266)", |  | ||||||
|                             action='store_true') |                             action='store_true') | ||||||
|  |  | ||||||
|     parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from " |     parser_clean = subparsers.add_parser('clean-mqtt', help="Helper to clear an MQTT topic from " | ||||||
| @@ -432,6 +431,8 @@ def parse_args(argv): | |||||||
|     parser_clean.add_argument('--username', help='Manually set the username.') |     parser_clean.add_argument('--username', help='Manually set the username.') | ||||||
|     parser_clean.add_argument('--password', help='Manually set the password.') |     parser_clean.add_argument('--password', help='Manually set the password.') | ||||||
|     parser_clean.add_argument('--client-id', help='Manually set the client id.') |     parser_clean.add_argument('--client-id', help='Manually set the client id.') | ||||||
|  |     parser_clean.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|  |                               action='store_true') | ||||||
|  |  | ||||||
|     subparsers.add_parser('wizard', help="A helpful setup wizard that will guide " |     subparsers.add_parser('wizard', help="A helpful setup wizard that will guide " | ||||||
|                                          "you through setting up esphomeyaml.") |                                          "you through setting up esphomeyaml.") | ||||||
| @@ -440,7 +441,9 @@ def parse_args(argv): | |||||||
|  |  | ||||||
|     subparsers.add_parser('version', help="Print the esphomeyaml version and exit.") |     subparsers.add_parser('version', help="Print the esphomeyaml version and exit.") | ||||||
|  |  | ||||||
|     subparsers.add_parser('clean', help="Delete all temporary build files.") |     clean = subparsers.add_parser('clean', help="Delete all temporary build files.") | ||||||
|  |     clean.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|  |                        action='store_true') | ||||||
|  |  | ||||||
|     dashboard = subparsers.add_parser('dashboard', |     dashboard = subparsers.add_parser('dashboard', | ||||||
|                                       help="Create a simple web server for a dashboard.") |                                       help="Create a simple web server for a dashboard.") | ||||||
| @@ -455,14 +458,20 @@ def parse_args(argv): | |||||||
|                                 "add-on.", |                                 "add-on.", | ||||||
|                            action="store_true") |                            action="store_true") | ||||||
|  |  | ||||||
|     subparsers.add_parser('hass-config', help="Dump the configuration entries that should be added" |     hass_config = subparsers.add_parser('hass-config', | ||||||
|  |                                         help="Dump the configuration entries that should be added " | ||||||
|                                              "to Home Assistant when not using MQTT discovery.") |                                              "to Home Assistant when not using MQTT discovery.") | ||||||
|  |     hass_config.add_argument('--dashboard', help="Internal flag used by the dashboard", | ||||||
|  |                              action='store_true') | ||||||
|  |  | ||||||
|     return parser.parse_args(argv[1:]) |     return parser.parse_args(argv[1:]) | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_esphomeyaml(argv): | def run_esphomeyaml(argv): | ||||||
|     args = parse_args(argv) |     args = parse_args(argv) | ||||||
|  |     if hasattr(args, 'dashboard'): | ||||||
|  |         core.FROM_DASHBOARD = args.dashboard | ||||||
|  |  | ||||||
|     setup_log(args.verbose) |     setup_log(args.verbose) | ||||||
|     if args.command in PRE_CONFIG_ACTIONS: |     if args.command in PRE_CONFIG_ACTIONS: | ||||||
|         try: |         try: | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ WIFI_NETWORK_STA = WIFI_NETWORK_BASE.extend({ | |||||||
| def validate(config): | def validate(config): | ||||||
|     if CONF_PASSWORD in config and CONF_SSID not in config: |     if CONF_PASSWORD in config and CONF_SSID not in config: | ||||||
|         raise vol.Invalid("Cannot have WiFi password without SSID!") |         raise vol.Invalid("Cannot have WiFi password without SSID!") | ||||||
|     if CONF_SSID not in config and CONF_AP not in config: |     if (CONF_SSID not in config) and (CONF_AP not in config): | ||||||
|         raise vol.Invalid("Please specify at least an SSID or an Access Point " |         raise vol.Invalid("Please specify at least an SSID or an Access Point " | ||||||
|                           "to create.") |                           "to create.") | ||||||
|     return config |     return config | ||||||
|   | |||||||
| @@ -2,10 +2,10 @@ from __future__ import print_function | |||||||
|  |  | ||||||
| from collections import OrderedDict | from collections import OrderedDict | ||||||
| import importlib | import importlib | ||||||
|  | import json | ||||||
| import logging | import logging | ||||||
|  |  | ||||||
| import voluptuous as vol | import voluptuous as vol | ||||||
| from voluptuous.humanize import humanize_error |  | ||||||
|  |  | ||||||
| from esphomeyaml import core, core_config, yaml_util | from esphomeyaml import core, core_config, yaml_util | ||||||
| from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, CONF_WIFI, ESP_PLATFORMS | from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, CONF_WIFI, ESP_PLATFORMS | ||||||
| @@ -268,22 +268,53 @@ def validate_config(config): | |||||||
| REQUIRED = ['esphomeyaml', 'wifi'] | REQUIRED = ['esphomeyaml', 'wifi'] | ||||||
|  |  | ||||||
|  |  | ||||||
| def _format_config_error(ex, domain, config): | def _nested_getitem(data, path): | ||||||
|     message = u"Invalid config for [{}]: ".format(domain) |     for item_index in path: | ||||||
|  |         try: | ||||||
|  |             data = data[item_index] | ||||||
|  |         except (KeyError, IndexError, TypeError): | ||||||
|  |             return None | ||||||
|  |     return data | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _format_path(path): | ||||||
|  |     return u'->'.join(unicode(m) for m in path) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def humanize_error(config, validation_error): | ||||||
|  |     offending_item_summary = _nested_getitem(config, validation_error.path) | ||||||
|  |     if isinstance(offending_item_summary, dict): | ||||||
|  |         offending_item_summary = json.dumps(offending_item_summary) | ||||||
|  |     return u'{}. Got {}'.format(validation_error, offending_item_summary) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def _format_config_error(ex, domain, config, recursion=False): | ||||||
|  |     message = u"" if recursion else u"Invalid config for [{}]: ".format(domain) | ||||||
|  |     if isinstance(ex, vol.MultipleInvalid): | ||||||
|  |         return color('red', message + u'\n'.join(sorted( | ||||||
|  |             _format_config_error(sub_error, domain, config, recursion=True) | ||||||
|  |             for sub_error in ex.errors | ||||||
|  |         ))) | ||||||
|  |  | ||||||
|     if u'extra keys not allowed' in ex.error_message: |     if u'extra keys not allowed' in ex.error_message: | ||||||
|         message += u'[{}] is an invalid option for [{}]. Check: {}->{}.' \ |         message += u'[{}] is an invalid option for [{}].' \ | ||||||
|             .format(ex.path[-1], domain, domain, |             .format(ex.path[-1], domain) | ||||||
|                     u'->'.join(str(m) for m in ex.path)) |     elif u'required key not provided' in ex.error_message: | ||||||
|  |         message += u"'{}' is a required option for [{}]." \ | ||||||
|  |                    u"".format(ex.path[-1], domain) | ||||||
|     else: |     else: | ||||||
|         message += u'{}.'.format(humanize_error(config, ex)) |         message += u'{}.'.format(humanize_error(config, ex)) | ||||||
|  |  | ||||||
|  |     message += u' Check {}->{}.'.format(domain, _format_path(ex.path)) | ||||||
|  |     message = color('red', message) | ||||||
|  |  | ||||||
|     if isinstance(config, list): |     if isinstance(config, list): | ||||||
|         return message |         return message | ||||||
|  |  | ||||||
|     domain_config = config.get(domain, config) |     domain_config = config.get(domain, config) | ||||||
|     message += u" (See {}, line {}). ".format( |     message += color('cyan', u" (See {}, line {}). ".format( | ||||||
|         getattr(domain_config, '__config_file__', '?'), |         getattr(domain_config, '__config_file__', '?'), | ||||||
|         getattr(domain_config, '__line__', '?')) |         getattr(domain_config, '__line__', '?'))) | ||||||
|  |  | ||||||
|     return message |     return message | ||||||
|  |  | ||||||
| @@ -316,7 +347,7 @@ def line_info(obj, **kwargs): | |||||||
|     return '?' |     return '?' | ||||||
|  |  | ||||||
|  |  | ||||||
| def dump_dict(layer, indent_count=3, listi=False, **kwargs): | def dump_dict(layer, indent_count=0, listi=False, **kwargs): | ||||||
|     def sort_dict_key(val): |     def sort_dict_key(val): | ||||||
|         """Return the dict key for sorting.""" |         """Return the dict key for sorting.""" | ||||||
|         key = str.lower(val[0]) |         key = str.lower(val[0]) | ||||||
| @@ -358,9 +389,7 @@ def read_config(): | |||||||
|     if excepts: |     if excepts: | ||||||
|         safe_print(color('bold_white', u"Failed config")) |         safe_print(color('bold_white', u"Failed config")) | ||||||
|         for domain, config in excepts.iteritems(): |         for domain, config in excepts.iteritems(): | ||||||
|             safe_print(u' {} {}'.format(color('bold_red', domain + u':'), |             safe_print(color('bold_red', domain + u':')) | ||||||
|                                         color('red', '', reset='red'))) |             dump_dict(config) | ||||||
|             dump_dict(config, reset='red') |  | ||||||
|             safe_print(color('reset')) |  | ||||||
|         return None |         return None | ||||||
|     return OrderedDict(res) |     return OrderedDict(res) | ||||||
|   | |||||||
| @@ -398,3 +398,4 @@ CORE = EsphomeyamlCore() | |||||||
|  |  | ||||||
| ConfigType = Dict[str, Any] | ConfigType = Dict[str, Any] | ||||||
| CoreType = EsphomeyamlCore | CoreType = EsphomeyamlCore | ||||||
|  | FROM_DASHBOARD = False | ||||||
|   | |||||||
| @@ -105,7 +105,7 @@ class EsphomeyamlLogsHandler(EsphomeyamlCommandWebSocket): | |||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = CONFIG_DIR + '/' + js['configuration'] |         config_file = CONFIG_DIR + '/' + js['configuration'] | ||||||
|         return ["esphomeyaml", config_file, "logs", '--serial-port', js["port"], '--escape'] |         return ["esphomeyaml", config_file, "logs", '--serial-port', js["port"], '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket): | ||||||
| @@ -113,42 +113,42 @@ class EsphomeyamlRunHandler(EsphomeyamlCommandWebSocket): | |||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "run", '--upload-port', js["port"], |         return ["esphomeyaml", config_file, "run", '--upload-port', js["port"], | ||||||
|                 '--escape', '--use-esptoolpy'] |                 '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlCompileHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlCompileHandler(EsphomeyamlCommandWebSocket): | ||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "compile"] |         return ["esphomeyaml", config_file, "compile", '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlValidateHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlValidateHandler(EsphomeyamlCommandWebSocket): | ||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "config"] |         return ["esphomeyaml", config_file, "config", '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlCleanMqttHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlCleanMqttHandler(EsphomeyamlCommandWebSocket): | ||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "clean-mqtt"] |         return ["esphomeyaml", config_file, "clean-mqtt", '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlCleanHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlCleanHandler(EsphomeyamlCommandWebSocket): | ||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "clean"] |         return ["esphomeyaml", config_file, "clean", '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class EsphomeyamlHassConfigHandler(EsphomeyamlCommandWebSocket): | class EsphomeyamlHassConfigHandler(EsphomeyamlCommandWebSocket): | ||||||
|     def build_command(self, message): |     def build_command(self, message): | ||||||
|         js = json.loads(message) |         js = json.loads(message) | ||||||
|         config_file = os.path.join(CONFIG_DIR, js['configuration']) |         config_file = os.path.join(CONFIG_DIR, js['configuration']) | ||||||
|         return ["esphomeyaml", config_file, "hass-config"] |         return ["esphomeyaml", config_file, "hass-config", '--dashboard'] | ||||||
|  |  | ||||||
|  |  | ||||||
| class SerialPortRequestHandler(BaseHandler): | class SerialPortRequestHandler(BaseHandler): | ||||||
|   | |||||||
| @@ -5,19 +5,19 @@ document.addEventListener('DOMContentLoaded', () => { | |||||||
| const colorReplace = (input) => { | const colorReplace = (input) => { | ||||||
| input = input.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); | input = input.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'"); | ||||||
| input = input.replace(/\\033\[(?:0;)?31m/g, '<span class="e">'); | input = input.replace(/\\033\[(?:0;)?31m/g, '<span class="e">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?31m/g, '<span class="e bold">'); | input = input.replace(/\\033\[(?:0?1;)?31m/g, '<span class="e bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?32m/g, '<span class="i">'); | input = input.replace(/\\033\[(?:0;)?32m/g, '<span class="i">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?32m/g, '<span class="i bold">'); | input = input.replace(/\\033\[(?:0?1;)?32m/g, '<span class="i bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?33m/g, '<span class="w">'); | input = input.replace(/\\033\[(?:0;)?33m/g, '<span class="w">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?33m/g, '<span class="w bold">'); | input = input.replace(/\\033\[(?:0?1;)?33m/g, '<span class="w bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?35m/g, '<span class="c">'); | input = input.replace(/\\033\[(?:0;)?35m/g, '<span class="c">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?35m/g, '<span class="c bold">'); | input = input.replace(/\\033\[(?:0?1;)?35m/g, '<span class="c bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?36m/g, '<span class="d">'); | input = input.replace(/\\033\[(?:0;)?36m/g, '<span class="d">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?36m/g, '<span class="d bold">'); | input = input.replace(/\\033\[(?:0?1;)?36m/g, '<span class="d bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?37m/g, '<span class="v">'); | input = input.replace(/\\033\[(?:0;)?37m/g, '<span class="v">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?37m/g, '<span class="v bold">'); | input = input.replace(/\\033\[(?:0?1;)?37m/g, '<span class="v bold">'); | ||||||
| input = input.replace(/\\033\[(?:0;)?38m/g, '<span class="vv">'); | input = input.replace(/\\033\[(?:0;)?38m/g, '<span class="vv">'); | ||||||
| input = input.replace(/\\033\[(?:1;)?38m/g, '<span class="vv bold">'); | input = input.replace(/\\033\[(?:0?1;)?38m/g, '<span class="vv bold">'); | ||||||
| input = input.replace(/\\033\[0m/g, '</span>'); | input = input.replace(/\\033\[0m/g, '</span>'); | ||||||
|  |  | ||||||
| return input; | return input; | ||||||
| @@ -330,6 +330,7 @@ upload.addEventListener('click', (e) => { | |||||||
|     }; |     }; | ||||||
|   }); |   }); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| downloadButton.addEventListener('click', () => { | downloadButton.addEventListener('click', () => { | ||||||
|   const link = document.createElement("a"); |   const link = document.createElement("a"); | ||||||
|   link.download = name; |   link.download = name; | ||||||
| @@ -540,4 +541,5 @@ $('.stepper').activateStepper({ | |||||||
|     parallel: false |     parallel: false | ||||||
|   }); |   }); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| setupWizardStart.addEventListener('click', startWizard); | setupWizardStart.addEventListener('click', startWizard); | ||||||
| @@ -49,12 +49,18 @@ def cpp_string_escape(string, encoding='utf-8'): | |||||||
|     return '"' + result + '"' |     return '"' + result + '"' | ||||||
|  |  | ||||||
|  |  | ||||||
| def color(the_color, message='', reset=None): | def color(the_color, message=''): | ||||||
|     """Color helper.""" |     from esphomeyaml import core | ||||||
|     from colorlog.escape_codes import escape_codes, parse_colors |     from colorlog.escape_codes import escape_codes, parse_colors | ||||||
|  |  | ||||||
|     if not message: |     if not message: | ||||||
|         return parse_colors(the_color) |         res = parse_colors(the_color) | ||||||
|     return parse_colors(the_color) + message + escape_codes[reset or 'reset'] |     else: | ||||||
|  |         res = parse_colors(the_color) + message + escape_codes['reset'] | ||||||
|  |  | ||||||
|  |     if core.FROM_DASHBOARD: | ||||||
|  |         res = res.replace('\033', '\\033') | ||||||
|  |     return res | ||||||
|  |  | ||||||
|  |  | ||||||
| def run_system_command(*args): | def run_system_command(*args): | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ import sys | |||||||
|  |  | ||||||
| import paho.mqtt.client as mqtt | import paho.mqtt.client as mqtt | ||||||
|  |  | ||||||
|  | from esphomeyaml import core | ||||||
| from esphomeyaml.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOMEYAML, \ | from esphomeyaml.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOMEYAML, \ | ||||||
|     CONF_LOG_TOPIC, CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SSL_FINGERPRINTS, \ |     CONF_LOG_TOPIC, CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_SSL_FINGERPRINTS, \ | ||||||
|     CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME |     CONF_TOPIC, CONF_TOPIC_PREFIX, CONF_USERNAME | ||||||
| @@ -54,7 +55,7 @@ def initialize(config, subscriptions, on_message, username, password, client_id) | |||||||
|     return 0 |     return 0 | ||||||
|  |  | ||||||
|  |  | ||||||
| def show_logs(config, topic=None, username=None, password=None, client_id=None, escape=False): | def show_logs(config, topic=None, username=None, password=None, client_id=None): | ||||||
|     if topic is not None: |     if topic is not None: | ||||||
|         pass  # already have topic |         pass  # already have topic | ||||||
|     elif CONF_MQTT in config: |     elif CONF_MQTT in config: | ||||||
| @@ -73,7 +74,7 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None, | |||||||
|     def on_message(client, userdata, msg): |     def on_message(client, userdata, msg): | ||||||
|         time = datetime.now().time().strftime(u'[%H:%M:%S]') |         time = datetime.now().time().strftime(u'[%H:%M:%S]') | ||||||
|         message = time + msg.payload |         message = time + msg.payload | ||||||
|         if escape: |         if core.FROM_DASHBOARD: | ||||||
|             message = message.replace('\033', '\\033') |             message = message.replace('\033', '\\033') | ||||||
|         safe_print(message) |         safe_print(message) | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user