From 629f2b128e7a8b8b916c8f0cd258a366b0c287d2 Mon Sep 17 00:00:00 2001 From: Otto Winter Date: Sat, 20 Oct 2018 12:41:00 +0200 Subject: [PATCH] Add MQTT publish JSON action and subscribe JSON trigger (#193) * Add MQTT publish JSON action and subscribe JSON trigger * Lint --- esphomeyaml/__main__.py | 22 ++-- esphomeyaml/components/mqtt.py | 49 ++++++- esphomeyaml/config.py | 14 +- esphomeyaml/const.py | 1 + esphomeyaml/helpers.py | 8 ++ esphomeyaml/mqtt.py | 11 +- esphomeyaml/util.py | 16 +++ esphomeyaml/wizard.py | 225 +++++++++++++++++---------------- esphomeyaml/writer.py | 1 + tests/test1.yaml | 19 +++ tests/test2.yaml | 7 + 11 files changed, 233 insertions(+), 140 deletions(-) diff --git a/esphomeyaml/__main__.py b/esphomeyaml/__main__.py index 9a60ebe130..5d4ddaf185 100644 --- a/esphomeyaml/__main__.py +++ b/esphomeyaml/__main__.py @@ -16,6 +16,7 @@ from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.helpers import AssignmentExpression, Expression, RawStatement, \ _EXPRESSIONS, add, \ add_job, color, flush_tasks, indent, quote, statement, relative_path +from esphomeyaml.util import safe_print _LOGGER = logging.getLogger(__name__) @@ -39,11 +40,11 @@ def choose_serial_port(config): if not result: return 'OTA' - print(u"Found multiple serial port options, please choose one:") + safe_print(u"Found multiple serial port options, please choose one:") for i, (res, desc) in enumerate(result): - print(u" [{}] {} ({})".format(i, res, desc)) - print(u" [{}] Over The Air ({})".format(len(result), get_upload_host(config))) - print() + safe_print(u" [{}] {} ({})".format(i, res, desc)) + safe_print(u" [{}] Over The Air ({})".format(len(result), get_upload_host(config))) + safe_print() while True: opt = raw_input('(number): ') if opt in result: @@ -55,7 +56,7 @@ def choose_serial_port(config): raise ValueError break except ValueError: - print(color('red', u"Invalid option: '{}'".format(opt))) + safe_print(color('red', u"Invalid option: '{}'".format(opt))) if opt == len(result): return 'OTA' return result[opt][0] @@ -111,10 +112,7 @@ def run_miniterm(config, port, escape=False): message = time + line if escape: message = message.replace('\033', '\\033') - try: - print(message) - except UnicodeEncodeError: - print(message.encode('ascii', 'backslashreplace')) + safe_print(message) def write_cpp(config): @@ -295,7 +293,7 @@ def strip_default_ids(config): def command_config(args, config): if not args.verbose: config = strip_default_ids(config) - print(yaml_util.dump(config)) + safe_print(yaml_util.dump(config)) return 0 @@ -354,7 +352,7 @@ def command_mqtt_fingerprint(args, config): def command_version(args): - print(u"Version: {}".format(const.__version__)) + safe_print(u"Version: {}".format(const.__version__)) return 0 @@ -496,7 +494,7 @@ def run_esphomeyaml(argv): except ESPHomeYAMLError as e: _LOGGER.error(e) return 1 - print(u"Unknown command {}".format(args.command)) + safe_print(u"Unknown command {}".format(args.command)) return 1 diff --git a/esphomeyaml/components/mqtt.py b/esphomeyaml/components/mqtt.py index 0aa24d84c0..98d43f6137 100644 --- a/esphomeyaml/components/mqtt.py +++ b/esphomeyaml/components/mqtt.py @@ -10,10 +10,10 @@ from esphomeyaml.const import CONF_BIRTH_MESSAGE, CONF_BROKER, CONF_CLIENT_ID, C CONF_DISCOVERY_PREFIX, CONF_DISCOVERY_RETAIN, CONF_ID, CONF_KEEPALIVE, CONF_LEVEL, \ CONF_LOG_TOPIC, CONF_ON_MESSAGE, CONF_PASSWORD, CONF_PAYLOAD, CONF_PORT, CONF_QOS, \ CONF_REBOOT_TIMEOUT, CONF_RETAIN, CONF_SHUTDOWN_MESSAGE, CONF_SSL_FINGERPRINTS, CONF_TOPIC, \ - CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, CONF_WILL_MESSAGE + CONF_TOPIC_PREFIX, CONF_TRIGGER_ID, CONF_USERNAME, CONF_WILL_MESSAGE, CONF_ON_JSON_MESSAGE from esphomeyaml.helpers import App, ArrayInitializer, Pvariable, RawExpression, \ StructInitializer, TemplateArguments, add, esphomelib_ns, optional, std_string, templatable, \ - uint8, bool_ + uint8, bool_, JsonObjectRef, process_lambda, JsonObjectConstRef def validate_message_just_topic(value): @@ -37,7 +37,9 @@ mqtt_ns = esphomelib_ns.namespace('mqtt') MQTTMessage = mqtt_ns.MQTTMessage MQTTClientComponent = mqtt_ns.MQTTClientComponent MQTTPublishAction = mqtt_ns.MQTTPublishAction +MQTTPublishJsonAction = mqtt_ns.MQTTPublishJsonAction MQTTMessageTrigger = mqtt_ns.MQTTMessageTrigger +MQTTJsonMessageTrigger = mqtt_ns.MQTTJsonMessageTrigger def validate_broker(value): @@ -79,9 +81,14 @@ CONFIG_SCHEMA = vol.Schema({ vol.Optional(CONF_REBOOT_TIMEOUT): cv.positive_time_period_milliseconds, vol.Optional(CONF_ON_MESSAGE): vol.All(cv.ensure_list, [automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTMessageTrigger), - vol.Required(CONF_TOPIC): cv.publish_topic, + vol.Required(CONF_TOPIC): cv.subscribe_topic, vol.Optional(CONF_QOS, default=0): cv.mqtt_qos, - })]) + })]), + vol.Optional(CONF_ON_JSON_MESSAGE): vol.All(cv.ensure_list, [automation.validate_automation({ + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MQTTJsonMessageTrigger), + vol.Required(CONF_TOPIC): cv.subscribe_topic, + vol.Optional(CONF_QOS, default=0): cv.mqtt_qos, + })]), }) @@ -160,6 +167,11 @@ def to_code(config): trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) automation.build_automation(trigger, std_string, conf) + for conf in config.get(CONF_ON_JSON_MESSAGE, []): + rhs = mqtt.make_json_message_trigger(conf[CONF_TOPIC], conf[CONF_QOS]) + trigger = Pvariable(conf[CONF_TRIGGER_ID], rhs) + automation.build_automation(trigger, JsonObjectConstRef, conf) + CONF_MQTT_PUBLISH = 'mqtt.publish' MQTT_PUBLISH_ACTION_SCHEMA = vol.Schema({ @@ -194,6 +206,35 @@ def mqtt_publish_action_to_code(config, action_id, arg_type): yield action +CONF_MQTT_PUBLISH_JSON = 'mqtt.publish_json' +MQTT_PUBLISH_JSON_ACTION_SCHEMA = vol.Schema({ + vol.Required(CONF_TOPIC): cv.templatable(cv.publish_topic), + vol.Required(CONF_PAYLOAD): cv.lambda_, + vol.Optional(CONF_QOS): cv.mqtt_qos, + vol.Optional(CONF_RETAIN): cv.boolean, +}) + + +@ACTION_REGISTRY.register(CONF_MQTT_PUBLISH_JSON, MQTT_PUBLISH_JSON_ACTION_SCHEMA) +def mqtt_publish_json_action_to_code(config, action_id, arg_type): + template_arg = TemplateArguments(arg_type) + rhs = App.Pget_mqtt_client().Pmake_publish_json_action(template_arg) + type = MQTTPublishJsonAction.template(template_arg) + action = Pvariable(action_id, rhs, type=type) + for template_ in templatable(config[CONF_TOPIC], arg_type, std_string): + yield None + add(action.set_topic(template_)) + + for lambda_ in process_lambda(config[CONF_PAYLOAD], [(arg_type, 'x'), (JsonObjectRef, 'root')]): + yield None + add(action.set_payload(lambda_)) + if CONF_QOS in config: + add(action.set_qos(config[CONF_QOS])) + if CONF_RETAIN in config: + add(action.set_retain(config[CONF_RETAIN])) + yield action + + def required_build_flags(config): if CONF_SSL_FINGERPRINTS in config: return '-DASYNC_TCP_SSL_ENABLED=1' diff --git a/esphomeyaml/config.py b/esphomeyaml/config.py index 2771fc42a6..814df4905b 100644 --- a/esphomeyaml/config.py +++ b/esphomeyaml/config.py @@ -11,6 +11,7 @@ from esphomeyaml import core, yaml_util, core_config from esphomeyaml.const import CONF_ESPHOMEYAML, CONF_PLATFORM, CONF_WIFI, ESP_PLATFORMS from esphomeyaml.core import ESPHomeYAMLError from esphomeyaml.helpers import color +from esphomeyaml.util import safe_print _LOGGER = logging.getLogger(__name__) @@ -306,17 +307,17 @@ def dump_dict(layer, indent_count=3, listi=False, **kwargs): if isinstance(layer, dict): for key, value in sorted(layer.items(), key=sort_dict_key): if isinstance(value, (dict, list)): - print(indent_str, key + ':', line_info(value, **kwargs)) + safe_print(u"{} {}: {}".format(indent_str, key, line_info(value, **kwargs))) dump_dict(value, indent_count + 2) else: - print(indent_str, key + ':', value) + safe_print(u"{} {}: {}".format(indent_str, key, value)) indent_str = indent_count * ' ' if isinstance(layer, (list, tuple)): for i in layer: if isinstance(i, dict): dump_dict(i, indent_count + 2, True) else: - print(' ', indent_str, i) + safe_print(u" {} {}".format(indent_str, i)) def read_config(path): @@ -334,10 +335,11 @@ def read_config(path): excepts[domain].append(config) if excepts: - print(color('bold_white', u"Failed config")) + safe_print(color('bold_white', u"Failed config")) for domain, config in excepts.iteritems(): - print(' ', color('bold_red', domain + ':'), color('red', '', reset='red')) + safe_print(u' {} {}'.format(color('bold_red', domain + u':'), + color('red', '', reset='red'))) dump_dict(config, reset='red') - print(color('reset')) + safe_print(color('reset')) return None return OrderedDict(res) diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index 7ae8ffe243..bad9a04c65 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -342,6 +342,7 @@ CONF_CRON = 'cron' CONF_POWER_SAVE_MODE = 'power_save_mode' CONF_POWER_ON_VALUE = 'power_on_value' CONF_ON_TAG = 'on_tag' +CONF_ON_JSON_MESSAGE = 'on_json_message' ALLOWED_NAME_CHARS = u'abcdefghijklmnopqrstuvwxyz0123456789_' ARDUINO_VERSION_ESP32_DEV = 'https://github.com/platformio/platform-espressif32.git#feature/stage' diff --git a/esphomeyaml/helpers.py b/esphomeyaml/helpers.py index 601205aa87..b28eca3115 100644 --- a/esphomeyaml/helpers.py +++ b/esphomeyaml/helpers.py @@ -536,6 +536,10 @@ class MockObj(Expression): obj = MockObj(u'{} &'.format(self.base), u'') obj.requires.append(self) return obj + if name == "const": + obj = MockObj(u'const {}'.format(self.base), u'') + obj.requires.append(self) + return obj raise NotImplementedError() def has_side_effects(self): @@ -568,6 +572,10 @@ NoArg = esphomelib_ns.NoArg App = esphomelib_ns.App Application = esphomelib_ns.namespace('Application') optional = esphomelib_ns.optional +arduino_json_ns = global_ns.namespace('ArduinoJson') +JsonObject = arduino_json_ns.JsonObject +JsonObjectRef = JsonObject.operator('ref') +JsonObjectConstRef = JsonObjectRef.operator('const') GPIOPin = esphomelib_ns.GPIOPin GPIOOutputPin = esphomelib_ns.GPIOOutputPin diff --git a/esphomeyaml/mqtt.py b/esphomeyaml/mqtt.py index 0160d51197..9ed0e1d7d5 100644 --- a/esphomeyaml/mqtt.py +++ b/esphomeyaml/mqtt.py @@ -14,6 +14,7 @@ from esphomeyaml.const import CONF_BROKER, CONF_DISCOVERY_PREFIX, CONF_ESPHOMEYA CONF_MQTT, CONF_NAME, CONF_PASSWORD, CONF_PORT, CONF_TOPIC_PREFIX, \ CONF_USERNAME, CONF_TOPIC, CONF_SSL_FINGERPRINTS from esphomeyaml.helpers import color +from esphomeyaml.util import safe_print _LOGGER = logging.getLogger(__name__) @@ -70,10 +71,7 @@ def show_logs(config, topic=None, username=None, password=None, client_id=None, message = time + msg.payload if escape: message = message.replace('\033', '\\033') - try: - print(message) - except UnicodeEncodeError: - print(message.encode('ascii', 'backslashreplace')) + safe_print(message) return initialize(config, [topic], on_message, username, password, client_id) @@ -113,6 +111,7 @@ def get_fingerprint(config): sha1 = hashlib.sha1(cert_der).hexdigest() - print(u"SHA1 Fingerprint: " + color('cyan', sha1)) - print(u"Copy above string into mqtt.ssl_fingerprints section of {}".format(core.CONFIG_PATH)) + safe_print(u"SHA1 Fingerprint: " + color('cyan', sha1)) + safe_print(u"Copy the string above into mqtt.ssl_fingerprints section of {}" + u"".format(core.CONFIG_PATH)) return 0 diff --git a/esphomeyaml/util.py b/esphomeyaml/util.py index e54e3758c1..c52b54284f 100644 --- a/esphomeyaml/util.py +++ b/esphomeyaml/util.py @@ -1,3 +1,6 @@ +from __future__ import print_function + + class Registry(dict): def register(self, name): def decorator(fun): @@ -14,3 +17,16 @@ class ServiceRegistry(dict): return fun return decorator + + +def safe_print(message=""): + try: + print(message) + return + except UnicodeEncodeError: + pass + + try: + print(message.encode('ascii', 'backslashreplace')) + except UnicodeEncodeError: + print("Cannot print line because of invalid locale!") diff --git a/esphomeyaml/wizard.py b/esphomeyaml/wizard.py index 6b5c43471c..b250bc151c 100644 --- a/esphomeyaml/wizard.py +++ b/esphomeyaml/wizard.py @@ -6,14 +6,13 @@ import unicodedata import voluptuous as vol -import esphomeyaml.config_validation as cv from esphomeyaml.components import mqtt +import esphomeyaml.config_validation as cv from esphomeyaml.const import ESP_PLATFORMS, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 from esphomeyaml.helpers import color - - # pylint: disable=anomalous-backslash-in-string from esphomeyaml.pins import ESP32_BOARD_PINS, ESP8266_BOARD_PINS +from esphomeyaml.util import safe_print CORE_BIG = """ _____ ____ _____ ______ / ____/ __ \| __ \| ____| @@ -52,7 +51,7 @@ OTA_BIG = """ ____ _______ """ # TODO handle escaping -BASE_CONFIG = """esphomeyaml: +BASE_CONFIG = u"""esphomeyaml: name: {name} platform: {platform} board: {board} @@ -76,9 +75,9 @@ def wizard_file(**kwargs): config = BASE_CONFIG.format(**kwargs) if kwargs['ota_password']: - config += "ota:\n password: '{}'\n".format(kwargs['ota_password']) + config += u"ota:\n password: '{}'\n".format(kwargs['ota_password']) else: - config += "ota:\n" + config += u"ota:\n" return config @@ -90,18 +89,18 @@ else: from time import sleep -def print_step(step, big): - print() - print() - print("============= STEP {} =============".format(step)) - print(big) - print("===================================") +def safe_print_step(step, big): + safe_print() + safe_print() + safe_print("============= STEP {} =============".format(step)) + safe_print(big) + safe_print("===================================") sleep(0.25) def default_input(text, default): - print() - print("Press ENTER for default ({})".format(default)) + safe_print() + safe_print(u"Press ENTER for default ({})".format(default)) return raw_input(text.format(default)) or default @@ -113,30 +112,30 @@ def strip_accents(string): def wizard(path): if not path.endswith('.yaml') and not path.endswith('.yml'): - print("Please make your configuration file {} have the extension .yaml or .yml".format( - color('cyan', path))) + safe_print(u"Please make your configuration file {} have the extension .yaml or .yml" + u"".format(color('cyan', path))) return 1 if os.path.exists(path): - print("Uh oh, it seems like {} already exists, please delete that file first " - "or chose another configuration file.".format(color('cyan', 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))) return 1 - print("Hi there!") + safe_print("Hi there!") sleep(1.5) - print("I'm the wizard of esphomeyaml :)") + safe_print("I'm the wizard of esphomeyaml :)") sleep(1.25) - print("And I'm here to help you get started with esphomeyaml.") + safe_print("And I'm here to help you get started with esphomeyaml.") sleep(2.0) - print("In 5 steps I'm going to guide you through creating a basic " - "configuration file for your custom ESP8266/ESP32 firmware. Yay!") + safe_print("In 5 steps I'm going to guide you through creating a basic " + "configuration file for your custom ESP8266/ESP32 firmware. Yay!") sleep(3.0) - print() - print_step(1, CORE_BIG) - print("First up, please choose a " + color('green', 'name') + " for your node.") - print("It should be a unique name that can be used to identify the device later.") + 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.") sleep(1) - print("For example, I like calling the node in my living room {}.".format( + safe_print("For example, I like calling the node in my living room {}.".format( color('bold_white', "livingroom"))) - print() + safe_print() sleep(1) name = raw_input(color("bold_white", "(name): ")) while True: @@ -144,34 +143,34 @@ def wizard(path): name = cv.valid_name(name) break except vol.Invalid: - print(color("red", "Oh noes, \"{}\" isn't a valid name. Names can only include " - "numbers, letters and underscores.".format(name))) + safe_print(color("red", u"Oh noes, \"{}\" isn't a valid name. Names can only include " + u"numbers, letters and underscores.".format(name))) name = strip_accents(name).replace(' ', '_') name = u''.join(c for c in name if c in cv.ALLOWED_NAME_CHARS) - print("Shall I use \"{}\" as the name instead?".format(color('cyan', name))) + safe_print(u"Shall I use \"{}\" as the name instead?".format(color('cyan', name))) sleep(0.5) - name = default_input("(name [{}]): ", name) + name = default_input(u"(name [{}]): ", name) - print("Great! Your node is now called \"{}\".".format(color('cyan', name))) + safe_print(u"Great! Your node is now called \"{}\".".format(color('cyan', name))) sleep(1) - print_step(2, ESP_BIG) - print("Now I'd like to know what microcontroller you're using so that I can compile " - "firmwares for it.") - print("Are you using an " + color('green', 'ESP32') + " or " + - color('green', 'ESP8266') + " platform? (Choose ESP8266 for Sonoff devices)") + 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)") while True: sleep(0.5) - print() - print("Please enter either ESP32 or ESP8266.") + safe_print() + safe_print("Please enter either ESP32 or ESP8266.") platform = raw_input(color("bold_white", "(ESP32/ESP8266): ")) try: platform = vol.All(vol.Upper, vol.Any(*ESP_PLATFORMS))(platform) break except vol.Invalid: - print("Unfortunately, I can't find an espressif microcontroller called " - "\"{}\". Please try again.".format(platform)) - print("Thanks! You've chosen {} as your platform.".format(color('cyan', platform))) - print() + 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() sleep(1) if platform == ESP_PLATFORM_ESP32: @@ -179,18 +178,18 @@ def wizard(path): else: board_link = 'http://docs.platformio.org/en/latest/platforms/espressif8266.html#boards' - print("Next, I need to know what " + color('green', 'board') + " you're using.") + safe_print("Next, I need to know what " + color('green', 'board') + " you're using.") sleep(0.5) - print("Please go to {} and choose a board.".format(color('green', board_link))) + safe_print("Please go to {} and choose a board.".format(color('green', board_link))) if platform == ESP_PLATFORM_ESP8266: - print("(Type " + color('green', 'esp01_1m') + " for Sonoff devices)") - print() + safe_print("(Type " + color('green', 'esp01_1m') + " for Sonoff devices)") + safe_print() # Don't sleep because user needs to copy link if platform == ESP_PLATFORM_ESP32: - print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s'))) + safe_print("For example \"{}\".".format(color("bold_white", 'nodemcu-32s'))) boards = list(ESP32_BOARD_PINS.keys()) else: - print("For example \"{}\".".format(color("bold_white", 'nodemcuv2'))) + safe_print("For example \"{}\".".format(color("bold_white", 'nodemcuv2'))) boards = list(ESP8266_BOARD_PINS.keys()) while True: board = raw_input(color("bold_white", "(board): ")) @@ -198,71 +197,73 @@ def wizard(path): board = vol.All(vol.Lower, vol.Any(*boards))(board) break except vol.Invalid: - print(color('red', "Sorry, I don't think the board \"{}\" exists.")) - print() + safe_print(color('red', "Sorry, I don't think the board \"{}\" exists.")) + safe_print() sleep(0.25) - print("Possible options are {}".format(', '.join(boards))) - print() + safe_print("Possible options are {}".format(', '.join(boards))) + safe_print() - print("Way to go! You've chosen {} as your board.".format(color('cyan', board))) - print() + safe_print(u"Way to go! You've chosen {} as your board.".format(color('cyan', board))) + safe_print() sleep(1) - print_step(3, WIFI_BIG) - print("In this step, I'm going to create the configuration for " - "WiFi.") - print() + safe_print_step(3, WIFI_BIG) + safe_print("In this step, I'm going to create the configuration for " + "WiFi.") + safe_print() sleep(1) - print("First, what's the " + color('green', 'SSID') + " (the name) of the WiFi network {} " - "I should connect to?".format(name)) + safe_print("First, what's the " + color('green', 'SSID') + + u" (the name) of the WiFi network {} I should connect to?".format(name)) sleep(1.5) - print("For example \"{}\".".format(color('bold_white', "Abraham Linksys"))) + safe_print("For example \"{}\".".format(color('bold_white', "Abraham Linksys"))) while True: ssid = raw_input(color('bold_white', "(ssid): ")) try: ssid = cv.ssid(ssid) break except vol.Invalid: - print(color('red', "Unfortunately, \"{}\" doesn't seem to be a valid SSID. " - "Please try again.".format(ssid))) - print() + safe_print(color('red', u"Unfortunately, \"{}\" doesn't seem to be a valid SSID. " + u"Please try again.".format(ssid))) + safe_print() sleep(1) - print("Thank you very much! You've just chosen \"{}\" as your SSID.".format( - color('cyan', ssid))) - print() + safe_print(u"Thank you very much! You've just chosen \"{}\" as your SSID." + u"".format(color('cyan', ssid))) + safe_print() sleep(0.75) - print("Now please state the " + color('green', 'password') + - " of the WiFi network so that I can connect to it (Leave empty for no password)") - print() - print("For example \"{}\"".format(color('bold_white', 'PASSWORD42'))) + 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'))) sleep(0.5) psk = raw_input(color('bold_white', '(PSK): ')) - print("Perfect! WiFi is now set up (you can create static IPs and so on later).") + safe_print("Perfect! WiFi is now set up (you can create static IPs and so on later).") sleep(1.5) - print_step(4, MQTT_BIG) - print("Almost there! Now let's setup MQTT so that your node can connect to the outside world.") - print() + safe_print_step(4, MQTT_BIG) + safe_print("Almost there! Now let's setup MQTT so that your node can connect to the " + "outside world.") + safe_print() sleep(1) - print("Please enter the " + color('green', 'address') + " of your MQTT broker.") - print() - print("For example \"{}\".".format(color('bold_white', '192.168.178.84'))) + safe_print("Please enter the " + color('green', 'address') + " of your MQTT broker.") + safe_print() + safe_print("For example \"{}\".".format(color('bold_white', '192.168.178.84'))) while True: broker = raw_input(color('bold_white', "(broker): ")) try: broker = mqtt.validate_broker(broker) break except vol.Invalid as err: - print(color('red', "The broker address \"{}\" seems to be invalid: {} :(".format( - broker, err))) - print("Please try again.") - print() + safe_print(color('red', u"The broker address \"{}\" seems to be invalid: {} :(" + u"".format(broker, err))) + safe_print("Please try again.") + safe_print() sleep(1) - print("Thanks! Now enter the " + color('green', 'username') + " and " + - color('green', 'password') + " for the MQTT broker. Leave empty for no authentication.") + safe_print("Thanks! Now enter the " + color('green', 'username') + " and " + + color('green', 'password') + + " for the MQTT broker. Leave empty for no authentication.") mqtt_username = raw_input(color('bold_white', '(username): ')) mqtt_password = '' if mqtt_username: @@ -271,19 +272,19 @@ def wizard(path): show = '*' * len(mqtt_password) if len(mqtt_password) >= 2: show = mqtt_password[:2] + '*' * len(mqtt_password) - print("MQTT Username: \"{}\"; Password: \"{}\"".format( - color('cyan', mqtt_username), color('cyan', show))) + safe_print(u"MQTT Username: \"{}\"; Password: \"{}\"" + u"".format(color('cyan', mqtt_username), color('cyan', show))) else: - print("No authentication for MQTT") + safe_print("No authentication for MQTT") - print_step(5, OTA_BIG) - print("Last step! esphomeyaml can automatically upload custom firmwares over WiFi " - "(over the air).") - print("This can be insecure if you do not trust the WiFi network. Do you want to set " - "an " + color('green', 'OTA password') + " for remote updates?") - print() + safe_print_step(5, OTA_BIG) + safe_print("Last step! esphomeyaml can automatically upload custom firmwares over WiFi " + "(over the air).") + safe_print("This can be insecure if you do not trust the WiFi network. Do you want to set " + "an " + color('green', 'OTA password') + " for remote updates?") + safe_print() sleep(0.25) - print("Press ENTER for no password") + safe_print("Press ENTER for no password") ota_password = raw_input(color('bold_white', '(password): ')) config = wizard_file(name=name, platform=platform, board=board, @@ -294,19 +295,19 @@ def wizard(path): with codecs.open(path, 'w') as f_handle: f_handle.write(config) - print() - print(color('cyan', "DONE! I've now written a new configuration file to ") + - color('bold_cyan', path)) - print() - print("Next steps:") - print(" > If you haven't already, enable MQTT discovery in Home Assistant:") - print() - print(color('bold_white', "# In your configuration.yaml")) - print(color('bold_white', "mqtt:")) - print(color('bold_white', " broker: {}".format(broker))) - print(color('bold_white', " # ...")) - print(color('bold_white', " discovery: True")) - print() - print(" > Then follow the rest of the getting started guide:") - print(" > https://esphomelib.com/esphomeyaml/guides/getting_started_command_line.html") + 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(" > If you haven't already, enable MQTT discovery in Home Assistant:") + safe_print() + safe_print(color('bold_white', "# In your configuration.yaml")) + safe_print(color('bold_white', "mqtt:")) + safe_print(color('bold_white', u" broker: {}".format(broker))) + safe_print(color('bold_white', " # ...")) + safe_print(color('bold_white', " discovery: True")) + safe_print() + safe_print(" > Then follow the rest of the getting started guide:") + safe_print(" > https://esphomelib.com/esphomeyaml/guides/getting_started_command_line.html") return 0 diff --git a/esphomeyaml/writer.py b/esphomeyaml/writer.py index c83078cbaf..c045fade11 100644 --- a/esphomeyaml/writer.py +++ b/esphomeyaml/writer.py @@ -102,6 +102,7 @@ def get_ini_content(config, path): build_flags |= get_build_flags(config, 'build_flags') build_flags |= get_build_flags(config, 'BUILD_FLAGS') build_flags.add(u"-DESPHOMEYAML_USE") + build_flags.add("-Wno-unused-variable") build_flags |= get_build_flags(config, 'required_build_flags') build_flags |= get_build_flags(config, 'REQUIRED_BUILD_FLAGS') diff --git a/tests/test1.yaml b/tests/test1.yaml index 6bf1a6cdfa..fc44caa29b 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -73,6 +73,24 @@ mqtt: then: - deep_sleep.enter: id: deep_sleep_1 + on_json_message: + topic: the/topic + then: + - lambda: |- + int data = x["my_data"]; + ESP_LOGD("main", "The data is: %d", data); + - light.turn_on: + id: living_room_lights + transition_length: !lambda |- + int length = 1000; + if (x.containsKey("length")) + length = x["length"]; + return length; + effect: !lambda |- + const char *effect = "None"; + if (x.containsKey("effect")) + effect = x["effect"]; + return effect; i2c: sda: 21 @@ -599,6 +617,7 @@ light: state = 0; - platform: rgb name: "Living Room Lights" + id: living_room_lights red: pca_0 green: pca_1 blue: pca_2 diff --git a/tests/test2.yaml b/tests/test2.yaml index 4bfeb73c9f..3e091f9b3e 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -76,7 +76,14 @@ sensor: - platform: mqtt_subscribe name: "MQTT Subscribe Sensor 1" topic: "mqtt/topic" + id: the_sensor qos: 2 + on_value: + - mqtt.publish_json: + topic: the/topic + payload: |- + root["key"] = id(the_sensor).value; + root["greeting"] = "Hello World"; - platform: cse7766 voltage: name: "CSE7766 Voltage"