mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Cleanup dashboard JS (#491)
* Cleanup dashboard JS * Add vscode * Save start_mark/end_mark * Updates * Updates * Remove need for cv.nameable It's a bit hacky but removes so much bloat from integrations * Add enum helper * Document APIs, and Improvements * Fixes * Fixes * Update PULL_REQUEST_TEMPLATE.md * Updates * Updates * Updates
This commit is contained in:
		| @@ -195,8 +195,13 @@ def clean_mqtt(config, args): | ||||
|     return mqtt.clear_topic(config, args.topic, args.username, args.password, args.client_id) | ||||
|  | ||||
|  | ||||
| def setup_log(debug=False): | ||||
|     log_level = logging.DEBUG if debug else logging.INFO | ||||
| def setup_log(debug=False, quiet=False): | ||||
|     if debug: | ||||
|         log_level = logging.DEBUG | ||||
|     elif quiet: | ||||
|         log_level = logging.CRITICAL | ||||
|     else: | ||||
|         log_level = logging.INFO | ||||
|     logging.basicConfig(level=log_level) | ||||
|     fmt = "%(levelname)s %(message)s" | ||||
|     colorfmt = "%(log_color)s{}%(reset)s".format(fmt) | ||||
| @@ -236,6 +241,13 @@ def command_config(args, config): | ||||
|     return 0 | ||||
|  | ||||
|  | ||||
| def command_vscode(args): | ||||
|     from esphome import vscode | ||||
|  | ||||
|     CORE.config_path = args.configuration | ||||
|     vscode.read_config() | ||||
|  | ||||
|  | ||||
| def command_compile(args, config): | ||||
|     exit_code = write_cpp(config) | ||||
|     if exit_code != 0: | ||||
| @@ -321,7 +333,8 @@ def command_dashboard(args): | ||||
| PRE_CONFIG_ACTIONS = { | ||||
|     'wizard': command_wizard, | ||||
|     'version': command_version, | ||||
|     'dashboard': command_dashboard | ||||
|     'dashboard': command_dashboard, | ||||
|     'vscode': command_vscode, | ||||
| } | ||||
|  | ||||
| POST_CONFIG_ACTIONS = { | ||||
| @@ -340,8 +353,9 @@ def parse_args(argv): | ||||
|     parser = argparse.ArgumentParser(prog='esphome') | ||||
|     parser.add_argument('-v', '--verbose', help="Enable verbose esphome logs.", | ||||
|                         action='store_true') | ||||
|     parser.add_argument('--dashboard', help="Internal flag to set if the command is run from the " | ||||
|                                             "dashboard.", action='store_true') | ||||
|     parser.add_argument('-q', '--quiet', help="Disable all esphome logs.", | ||||
|                         action='store_true') | ||||
|     parser.add_argument('--dashboard', help=argparse.SUPPRESS, action='store_true') | ||||
|     parser.add_argument('configuration', help='Your YAML configuration file.') | ||||
|  | ||||
|     subparsers = parser.add_subparsers(help='Commands', dest='command') | ||||
| @@ -404,12 +418,13 @@ def parse_args(argv): | ||||
|     dashboard.add_argument("--open-ui", help="Open the dashboard UI in a browser.", | ||||
|                            action='store_true') | ||||
|     dashboard.add_argument("--hassio", | ||||
|                            help="Internal flag used to tell esphome is started as a Hass.io " | ||||
|                                 "add-on.", | ||||
|                            help=argparse.SUPPRESS, | ||||
|                            action="store_true") | ||||
|     dashboard.add_argument("--socket", | ||||
|                            help="Make the dashboard serve under a unix socket", type=str) | ||||
|  | ||||
|     subparsers.add_parser('vscode', help=argparse.SUPPRESS) | ||||
|  | ||||
|     return parser.parse_args(argv[1:]) | ||||
|  | ||||
|  | ||||
| @@ -417,7 +432,7 @@ def run_esphome(argv): | ||||
|     args = parse_args(argv) | ||||
|     CORE.dashboard = args.dashboard | ||||
|  | ||||
|     setup_log(args.verbose) | ||||
|     setup_log(args.verbose, args.quiet) | ||||
|     if args.command in PRE_CONFIG_ACTIONS: | ||||
|         try: | ||||
|             return PRE_CONFIG_ACTIONS[args.command](args) | ||||
|   | ||||
| @@ -1,15 +1,9 @@ | ||||
| import copy | ||||
|  | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import CONF_ABOVE, CONF_ACTION_ID, CONF_AND, CONF_AUTOMATION_ID, CONF_BELOW, \ | ||||
|     CONF_CONDITION, CONF_CONDITION_ID, CONF_DELAY, CONF_ELSE, CONF_ID, CONF_IF, CONF_LAMBDA, \ | ||||
|     CONF_OR, CONF_RANGE, CONF_THEN, CONF_TRIGGER_ID, CONF_WAIT_UNTIL, CONF_WHILE | ||||
| from esphome.const import CONF_AUTOMATION_ID, CONF_CONDITION, CONF_ELSE, CONF_ID, CONF_THEN, \ | ||||
|     CONF_TRIGGER_ID, CONF_TYPE_ID | ||||
| from esphome.core import coroutine | ||||
| from esphome.cpp_generator import Pvariable, TemplateArguments, add, get_variable, \ | ||||
|     process_lambda, templatable | ||||
| from esphome.cpp_types import Action, App, Component, PollingComponent, Trigger, bool_, \ | ||||
|     esphome_ns, float_, uint32, void | ||||
| from esphome.util import ServiceRegistry | ||||
| from esphome.util import Registry | ||||
|  | ||||
|  | ||||
| def maybe_simple_id(*validators): | ||||
| @@ -18,97 +12,49 @@ def maybe_simple_id(*validators): | ||||
|     def validate(value): | ||||
|         if isinstance(value, dict): | ||||
|             return validator(value) | ||||
|         return validator({CONF_ID: value}) | ||||
|         with cv.remove_prepend_path([CONF_ID]): | ||||
|             return validator({CONF_ID: value}) | ||||
|  | ||||
|     return validate | ||||
|  | ||||
|  | ||||
| def validate_recursive_condition(value): | ||||
|     is_list = isinstance(value, list) | ||||
|     value = cv.ensure_list()(value)[:] | ||||
|     for i, item in enumerate(value): | ||||
|         path = [i] if is_list else [] | ||||
|         item = copy.deepcopy(item) | ||||
|         if not isinstance(item, dict): | ||||
|             raise cv.Invalid(u"Condition must consist of key-value mapping! Got {}".format(item), | ||||
|                              path) | ||||
|         key = next((x for x in item if x != CONF_CONDITION_ID), None) | ||||
|         if key is None: | ||||
|             raise cv.Invalid(u"Key missing from action! Got {}".format(item), path) | ||||
|         if key not in CONDITION_REGISTRY: | ||||
|             raise cv.Invalid(u"Unable to find condition with the name '{}', is the " | ||||
|                              u"component loaded?".format(key), path + [key]) | ||||
|         item.setdefault(CONF_CONDITION_ID, None) | ||||
|         key2 = next((x for x in item if x not in (CONF_CONDITION_ID, key)), None) | ||||
|         if key2 is not None: | ||||
|             raise cv.Invalid(u"Cannot have two conditions in one item. Key '{}' overrides '{}'! " | ||||
|                              u"Did you forget to indent the block inside the condition?" | ||||
|                              u"".format(key, key2), path) | ||||
|         validator = CONDITION_REGISTRY[key][0] | ||||
|         try: | ||||
|             condition = validator(item[key] or {}) | ||||
|         except cv.Invalid as err: | ||||
|             err.prepend(path) | ||||
|             raise err | ||||
|         value[i] = { | ||||
|             CONF_CONDITION_ID: cv.declare_variable_id(Condition)(item[CONF_CONDITION_ID]), | ||||
|             key: condition, | ||||
|         } | ||||
|     return value | ||||
| def register_action(name, action_type, schema): | ||||
|     return ACTION_REGISTRY.register(name, action_type, schema) | ||||
|  | ||||
|  | ||||
| def validate_recursive_action(value): | ||||
|     is_list = isinstance(value, list) | ||||
|     if not is_list: | ||||
|         value = [value] | ||||
|     for i, item in enumerate(value): | ||||
|         path = [i] if is_list else [] | ||||
|         item = copy.deepcopy(item) | ||||
|         if not isinstance(item, dict): | ||||
|             raise cv.Invalid(u"Action must consist of key-value mapping! Got {}".format(item), | ||||
|                              path) | ||||
|         key = next((x for x in item if x != CONF_ACTION_ID), None) | ||||
|         if key is None: | ||||
|             raise cv.Invalid(u"Key missing from action! Got {}".format(item), path) | ||||
|         if key not in ACTION_REGISTRY: | ||||
|             raise cv.Invalid(u"Unable to find action with the name '{}', is the component loaded?" | ||||
|                              u"".format(key), path + [key]) | ||||
|         item.setdefault(CONF_ACTION_ID, None) | ||||
|         key2 = next((x for x in item if x not in (CONF_ACTION_ID, key)), None) | ||||
|         if key2 is not None: | ||||
|             raise cv.Invalid(u"Cannot have two actions in one item. Key '{}' overrides '{}'! " | ||||
|                              u"Did you forget to indent the block inside the action?" | ||||
|                              u"".format(key, key2), path) | ||||
|         validator = ACTION_REGISTRY[key][0] | ||||
|         try: | ||||
|             action = validator(item[key] or {}) | ||||
|         except cv.Invalid as err: | ||||
|             err.prepend(path) | ||||
|             raise err | ||||
|         value[i] = { | ||||
|             CONF_ACTION_ID: cv.declare_variable_id(Action)(item[CONF_ACTION_ID]), | ||||
|             key: action, | ||||
|         } | ||||
|     return value | ||||
| def register_condition(name, condition_type, schema): | ||||
|     return CONDITION_REGISTRY.register(name, condition_type, schema) | ||||
|  | ||||
|  | ||||
| ACTION_REGISTRY = ServiceRegistry() | ||||
| CONDITION_REGISTRY = ServiceRegistry() | ||||
| Action = cg.esphome_ns.class_('Action') | ||||
| Trigger = cg.esphome_ns.class_('Trigger') | ||||
| ACTION_REGISTRY = Registry() | ||||
| Condition = cg.esphome_ns.class_('Condition') | ||||
| CONDITION_REGISTRY = Registry() | ||||
| validate_action = cv.validate_registry_entry('action', ACTION_REGISTRY) | ||||
| validate_action_list = cv.validate_registry('action', ACTION_REGISTRY) | ||||
| validate_condition = cv.validate_registry_entry('condition', CONDITION_REGISTRY) | ||||
| validate_condition_list = cv.validate_registry('condition', CONDITION_REGISTRY) | ||||
|  | ||||
| # pylint: disable=invalid-name | ||||
| DelayAction = esphome_ns.class_('DelayAction', Action, Component) | ||||
| LambdaAction = esphome_ns.class_('LambdaAction', Action) | ||||
| IfAction = esphome_ns.class_('IfAction', Action) | ||||
| WhileAction = esphome_ns.class_('WhileAction', Action) | ||||
| WaitUntilAction = esphome_ns.class_('WaitUntilAction', Action, Component) | ||||
| UpdateComponentAction = esphome_ns.class_('UpdateComponentAction', Action) | ||||
| Automation = esphome_ns.class_('Automation') | ||||
|  | ||||
| Condition = esphome_ns.class_('Condition') | ||||
| AndCondition = esphome_ns.class_('AndCondition', Condition) | ||||
| OrCondition = esphome_ns.class_('OrCondition', Condition) | ||||
| RangeCondition = esphome_ns.class_('RangeCondition', Condition) | ||||
| LambdaCondition = esphome_ns.class_('LambdaCondition', Condition) | ||||
| def validate_potentially_and_condition(value): | ||||
|     if isinstance(value, list): | ||||
|         with cv.remove_prepend_path(['and']): | ||||
|             return validate_condition({ | ||||
|                 'and': value | ||||
|             }) | ||||
|     return validate_condition(value) | ||||
|  | ||||
|  | ||||
| DelayAction = cg.esphome_ns.class_('DelayAction', Action, cg.Component) | ||||
| LambdaAction = cg.esphome_ns.class_('LambdaAction', Action) | ||||
| IfAction = cg.esphome_ns.class_('IfAction', Action) | ||||
| WhileAction = cg.esphome_ns.class_('WhileAction', Action) | ||||
| WaitUntilAction = cg.esphome_ns.class_('WaitUntilAction', Action, cg.Component) | ||||
| UpdateComponentAction = cg.esphome_ns.class_('UpdateComponentAction', Action) | ||||
| Automation = cg.esphome_ns.class_('Automation') | ||||
|  | ||||
| LambdaCondition = cg.esphome_ns.class_('LambdaCondition', Condition) | ||||
|  | ||||
|  | ||||
| def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
| @@ -120,24 +66,26 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
|  | ||||
|     def validator_(value): | ||||
|         if isinstance(value, list): | ||||
|             # List of items, there are two possible options here, either a sequence of | ||||
|             # actions (no then:) or a list of automations. | ||||
|             try: | ||||
|                 # First try as a sequence of actions | ||||
|                 return [schema({CONF_THEN: value})] | ||||
|                 # If that succeeds, return immediately | ||||
|                 with cv.remove_prepend_path([CONF_THEN]): | ||||
|                     return [schema({CONF_THEN: value})] | ||||
|             except cv.Invalid as err: | ||||
|                 if err.path and err.path[0] == CONF_THEN: | ||||
|                     err.path.pop(0) | ||||
|  | ||||
|                 # Next try as a sequence of automations | ||||
|                 try: | ||||
|                     return cv.Schema([schema])(value) | ||||
|                 except cv.Invalid as err2: | ||||
|                     if 'Unable to find action' in str(err): | ||||
|                     if u'Unable to find action' in str(err): | ||||
|                         raise err2 | ||||
|                     raise cv.MultipleInvalid([err, err2]) | ||||
|                 raise cv.MultipleInvalid([err, err2]) | ||||
|         elif isinstance(value, dict): | ||||
|             if CONF_THEN in value: | ||||
|                 return [schema(value)] | ||||
|             return [schema({CONF_THEN: value})] | ||||
|             with cv.remove_prepend_path([CONF_THEN]): | ||||
|                 return [schema({CONF_THEN: value})] | ||||
|         # This should only happen with invalid configs, but let's have a nice error message. | ||||
|         return [schema(value)] | ||||
|  | ||||
| @@ -155,175 +103,119 @@ def validate_automation(extra_schema=None, extra_validators=None, single=False): | ||||
|  | ||||
|  | ||||
| AUTOMATION_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(Trigger), | ||||
|     cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_variable_id(Automation), | ||||
|     cv.Required(CONF_THEN): validate_recursive_action, | ||||
|     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(Trigger), | ||||
|     cv.GenerateID(CONF_AUTOMATION_ID): cv.declare_id(Automation), | ||||
|     cv.Required(CONF_THEN): validate_action_list, | ||||
| }) | ||||
|  | ||||
| AND_CONDITION_SCHEMA = validate_recursive_condition | ||||
| AndCondition = cg.esphome_ns.class_('AndCondition', Condition) | ||||
| OrCondition = cg.esphome_ns.class_('OrCondition', Condition) | ||||
| NotCondition = cg.esphome_ns.class_('NotCondition', Condition) | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register(CONF_AND, AND_CONDITION_SCHEMA) | ||||
| @register_condition('and', AndCondition, validate_condition_list) | ||||
| def and_condition_to_code(config, condition_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config, template_arg, args) | ||||
|     rhs = AndCondition.new(template_arg, conditions) | ||||
|     type = AndCondition.template(template_arg) | ||||
|     yield Pvariable(condition_id, rhs, type=type) | ||||
|     conditions = yield build_condition_list(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, conditions) | ||||
|  | ||||
|  | ||||
| OR_CONDITION_SCHEMA = validate_recursive_condition | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register(CONF_OR, OR_CONDITION_SCHEMA) | ||||
| @register_condition('or', OrCondition, validate_condition_list) | ||||
| def or_condition_to_code(config, condition_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config, template_arg, args) | ||||
|     rhs = OrCondition.new(template_arg, conditions) | ||||
|     type = OrCondition.template(template_arg) | ||||
|     yield Pvariable(condition_id, rhs, type=type) | ||||
|     conditions = yield build_condition_list(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, conditions) | ||||
|  | ||||
|  | ||||
| RANGE_CONDITION_SCHEMA = cv.All(cv.Schema({ | ||||
|     cv.Optional(CONF_ABOVE): cv.templatable(cv.float_), | ||||
|     cv.Optional(CONF_BELOW): cv.templatable(cv.float_), | ||||
| }), cv.has_at_least_one_key(CONF_ABOVE, CONF_BELOW)) | ||||
| @register_condition('not', NotCondition, validate_condition) | ||||
| def not_condition_to_code(config, condition_id, template_arg, args): | ||||
|     condition = yield build_condition(config, template_arg, args) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, condition) | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register(CONF_RANGE, RANGE_CONDITION_SCHEMA) | ||||
| def range_condition_to_code(config, condition_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config, template_arg, args) | ||||
|     rhs = RangeCondition.new(template_arg, conditions) | ||||
|     type = RangeCondition.template(template_arg) | ||||
|     condition = Pvariable(condition_id, rhs, type=type) | ||||
|     if CONF_ABOVE in config: | ||||
|         template_ = yield templatable(config[CONF_ABOVE], args, float_) | ||||
|         condition.set_min(template_) | ||||
|     if CONF_BELOW in config: | ||||
|         template_ = yield templatable(config[CONF_BELOW], args, float_) | ||||
|         condition.set_max(template_) | ||||
|     yield condition | ||||
| @register_condition('lambda', LambdaCondition, cv.lambda_) | ||||
| def lambda_condition_to_code(config, condition_id, template_arg, args): | ||||
|     lambda_ = yield cg.process_lambda(config, args, return_type=bool) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, lambda_) | ||||
|  | ||||
|  | ||||
| DELAY_ACTION_SCHEMA = cv.templatable(cv.positive_time_period_milliseconds) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_DELAY, DELAY_ACTION_SCHEMA) | ||||
| @register_action('delay', DelayAction, cv.templatable(cv.positive_time_period_milliseconds)) | ||||
| def delay_action_to_code(config, action_id, template_arg, args): | ||||
|     rhs = App.register_component(DelayAction.new(template_arg)) | ||||
|     type = DelayAction.template(template_arg) | ||||
|     action = Pvariable(action_id, rhs, type=type) | ||||
|     template_ = yield templatable(config, args, uint32) | ||||
|     add(action.set_delay(template_)) | ||||
|     yield action | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     yield cg.register_component(var, {}) | ||||
|     template_ = yield cg.templatable(config, args, cg.uint32) | ||||
|     cg.add(var.set_delay(template_)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| IF_ACTION_SCHEMA = cv.All({ | ||||
|     cv.Required(CONF_CONDITION): validate_recursive_condition, | ||||
|     cv.Optional(CONF_THEN): validate_recursive_action, | ||||
|     cv.Optional(CONF_ELSE): validate_recursive_action, | ||||
| }, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE)) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_IF, IF_ACTION_SCHEMA) | ||||
| @register_action('if', IfAction, cv.All({ | ||||
|     cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     cv.Optional(CONF_THEN): validate_action_list, | ||||
|     cv.Optional(CONF_ELSE): validate_action_list, | ||||
| }, cv.has_at_least_one_key(CONF_THEN, CONF_ELSE))) | ||||
| def if_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) | ||||
|     rhs = IfAction.new(template_arg, conditions) | ||||
|     type = IfAction.template(template_arg) | ||||
|     action = Pvariable(action_id, rhs, type=type) | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
|     if CONF_THEN in config: | ||||
|         actions = yield build_actions(config[CONF_THEN], template_arg, args) | ||||
|         add(action.add_then(actions)) | ||||
|         actions = yield build_action_list(config[CONF_THEN], template_arg, args) | ||||
|         cg.add(var.add_then(actions)) | ||||
|     if CONF_ELSE in config: | ||||
|         actions = yield build_actions(config[CONF_ELSE], template_arg, args) | ||||
|         add(action.add_else(actions)) | ||||
|     yield action | ||||
|         actions = yield build_action_list(config[CONF_ELSE], template_arg, args) | ||||
|         cg.add(var.add_else(actions)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| WHILE_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_CONDITION): validate_recursive_condition, | ||||
|     cv.Required(CONF_THEN): validate_recursive_action, | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_WHILE, WHILE_ACTION_SCHEMA) | ||||
| @register_action('while', WhileAction, cv.Schema({ | ||||
|     cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     cv.Required(CONF_THEN): validate_action_list, | ||||
| })) | ||||
| def while_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) | ||||
|     rhs = WhileAction.new(template_arg, conditions) | ||||
|     type = WhileAction.template(template_arg) | ||||
|     action = Pvariable(action_id, rhs, type=type) | ||||
|     actions = yield build_actions(config[CONF_THEN], template_arg, args) | ||||
|     add(action.add_then(actions)) | ||||
|     yield action | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
|     actions = yield build_action_list(config[CONF_THEN], template_arg, args) | ||||
|     cg.add(var.add_then(actions)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| def validate_wait_until(value): | ||||
|     schema = cv.Schema({ | ||||
|         cv.Required(CONF_CONDITION): validate_recursive_condition | ||||
|         cv.Required(CONF_CONDITION): validate_potentially_and_condition, | ||||
|     }) | ||||
|     if isinstance(value, dict) and CONF_CONDITION in value: | ||||
|         return schema(value) | ||||
|     return validate_wait_until({CONF_CONDITION: value}) | ||||
|  | ||||
|  | ||||
| WAIT_UNTIL_ACTION_SCHEMA = validate_wait_until | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_WAIT_UNTIL, WAIT_UNTIL_ACTION_SCHEMA) | ||||
| @register_action('wait_until', WaitUntilAction, validate_wait_until) | ||||
| def wait_until_action_to_code(config, action_id, template_arg, args): | ||||
|     conditions = yield build_conditions(config[CONF_CONDITION], template_arg, args) | ||||
|     rhs = WaitUntilAction.new(template_arg, conditions) | ||||
|     type = WaitUntilAction.template(template_arg) | ||||
|     action = Pvariable(action_id, rhs, type=type) | ||||
|     add(App.register_component(action)) | ||||
|     yield action | ||||
|     conditions = yield build_condition(config[CONF_CONDITION], template_arg, args) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, conditions) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| LAMBDA_ACTION_SCHEMA = cv.lambda_ | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_LAMBDA, LAMBDA_ACTION_SCHEMA) | ||||
| @register_action('lambda', LambdaAction, cv.lambda_) | ||||
| def lambda_action_to_code(config, action_id, template_arg, args): | ||||
|     lambda_ = yield process_lambda(config, args, return_type=void) | ||||
|     rhs = LambdaAction.new(template_arg, lambda_) | ||||
|     type = LambdaAction.template(template_arg) | ||||
|     yield Pvariable(action_id, rhs, type=type) | ||||
|     lambda_ = yield cg.process_lambda(config, args, return_type=cg.void) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, lambda_) | ||||
|  | ||||
|  | ||||
| LAMBDA_CONDITION_SCHEMA = cv.lambda_ | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register(CONF_LAMBDA, LAMBDA_CONDITION_SCHEMA) | ||||
| def lambda_condition_to_code(config, condition_id, template_arg, args): | ||||
|     lambda_ = yield process_lambda(config, args, return_type=bool_) | ||||
|     rhs = LambdaCondition.new(template_arg, lambda_) | ||||
|     type = LambdaCondition.template(template_arg) | ||||
|     yield Pvariable(condition_id, rhs, type=type) | ||||
|  | ||||
|  | ||||
| CONF_COMPONENT_UPDATE = 'component.update' | ||||
| COMPONENT_UPDATE_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(PollingComponent), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_COMPONENT_UPDATE, COMPONENT_UPDATE_ACTION_SCHEMA) | ||||
| @register_action('component.update', UpdateComponentAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(cg.PollingComponent), | ||||
| })) | ||||
| def component_update_action_to_code(config, action_id, template_arg, args): | ||||
|     var = yield get_variable(config[CONF_ID]) | ||||
|     rhs = UpdateComponentAction.new(template_arg, var) | ||||
|     type = UpdateComponentAction.template(template_arg) | ||||
|     yield Pvariable(action_id, rhs, type=type) | ||||
|     comp = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, comp) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def build_action(full_config, template_arg, args): | ||||
|     action_id = full_config[CONF_ACTION_ID] | ||||
|     key, config = next((k, v) for k, v in full_config.items() if k in ACTION_REGISTRY) | ||||
|  | ||||
|     builder = coroutine(ACTION_REGISTRY[key][1]) | ||||
|     registry_entry, config = cg.extract_registry_entry_config(ACTION_REGISTRY, full_config) | ||||
|     action_id = full_config[CONF_TYPE_ID] | ||||
|     builder = registry_entry.coroutine_fun | ||||
|     yield builder(config, action_id, template_arg, args) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def build_actions(config, templ, arg_type): | ||||
| def build_action_list(config, templ, arg_type): | ||||
|     actions = [] | ||||
|     for conf in config: | ||||
|         action = yield build_action(conf, templ, arg_type) | ||||
| @@ -333,15 +225,14 @@ def build_actions(config, templ, arg_type): | ||||
|  | ||||
| @coroutine | ||||
| def build_condition(full_config, template_arg, args): | ||||
|     action_id = full_config[CONF_CONDITION_ID] | ||||
|     key, config = next((k, v) for k, v in full_config.items() if k in CONDITION_REGISTRY) | ||||
|  | ||||
|     builder = coroutine(CONDITION_REGISTRY[key][1]) | ||||
|     registry_entry, config = cg.extract_registry_entry_config(CONDITION_REGISTRY, full_config) | ||||
|     action_id = full_config[CONF_TYPE_ID] | ||||
|     builder = registry_entry.coroutine_fun | ||||
|     yield builder(config, action_id, template_arg, args) | ||||
|  | ||||
|  | ||||
| @coroutine | ||||
| def build_conditions(config, templ, args): | ||||
| def build_condition_list(config, templ, args): | ||||
|     conditions = [] | ||||
|     for conf in config: | ||||
|         condition = yield build_condition(conf, templ, args) | ||||
| @@ -352,10 +243,8 @@ def build_conditions(config, templ, args): | ||||
| @coroutine | ||||
| def build_automation(trigger, args, config): | ||||
|     arg_types = [arg[0] for arg in args] | ||||
|     templ = TemplateArguments(*arg_types) | ||||
|     type = Automation.template(templ) | ||||
|     rhs = type.new(trigger) | ||||
|     obj = Pvariable(config[CONF_AUTOMATION_ID], rhs, type=type) | ||||
|     actions = yield build_actions(config[CONF_THEN], templ, args) | ||||
|     add(obj.add_actions(actions)) | ||||
|     templ = cg.TemplateArguments(*arg_types) | ||||
|     obj = cg.new_Pvariable(config[CONF_AUTOMATION_ID], templ, trigger) | ||||
|     actions = yield build_action_list(config[CONF_THEN], templ, args) | ||||
|     cg.add(obj.add_actions(actions)) | ||||
|     yield obj | ||||
|   | ||||
| @@ -17,10 +17,10 @@ from esphome.cpp_generator import (  # noqa | ||||
|     MockObjClass) | ||||
| from esphome.cpp_helpers import (  # noqa | ||||
|     gpio_pin_expression, register_component, build_registry_entry, | ||||
|     build_registry_list) | ||||
|     build_registry_list, extract_registry_entry_config) | ||||
| from esphome.cpp_types import (  # noqa | ||||
|     global_ns, void, nullptr, float_, bool_, std_ns, std_string, | ||||
|     std_vector, uint8, uint16, uint32, int32, const_char_ptr, NAN, | ||||
|     esphome_ns, App, Nameable, Trigger, Action, Component, ComponentPtr, | ||||
|     esphome_ns, App, Nameable, Component, ComponentPtr, | ||||
|     PollingComponent, Application, optional, arduino_json_ns, JsonObject, | ||||
|     JsonObjectRef, JsonObjectConstRef, Controller, GPIOPin) | ||||
|   | ||||
| @@ -9,7 +9,8 @@ namespace a4988 { | ||||
|  | ||||
| class A4988 : public stepper::Stepper, public Component { | ||||
|  public: | ||||
|   A4988(GPIOPin *step_pin, GPIOPin *dir_pin) : step_pin_(step_pin), dir_pin_(dir_pin) {} | ||||
|   void set_step_pin(GPIOPin *step_pin) { step_pin_ = step_pin; } | ||||
|   void set_dir_pin(GPIOPin *dir_pin) { dir_pin_ = dir_pin; } | ||||
|   void set_sleep_pin(GPIOPin *sleep_pin) { this->sleep_pin_ = sleep_pin; } | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   | ||||
| @@ -9,7 +9,7 @@ a4988_ns = cg.esphome_ns.namespace('a4988') | ||||
| A4988 = a4988_ns.class_('A4988', stepper.Stepper, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_variable_id(A4988), | ||||
|     cv.Required(CONF_ID): cv.declare_id(A4988), | ||||
|     cv.Required(CONF_STEP_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Required(CONF_DIR_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_SLEEP_PIN): pins.gpio_output_pin_schema, | ||||
| @@ -17,12 +17,15 @@ CONFIG_SCHEMA = stepper.STEPPER_SCHEMA.extend({ | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     step_pin = yield cg.gpio_pin_expression(config[CONF_STEP_PIN]) | ||||
|     dir_pin = yield cg.gpio_pin_expression(config[CONF_DIR_PIN]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], step_pin, dir_pin) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield stepper.register_stepper(var, config) | ||||
|  | ||||
|     step_pin = yield cg.gpio_pin_expression(config[CONF_STEP_PIN]) | ||||
|     cg.add(var.set_step_pin(step_pin)) | ||||
|     dir_pin = yield cg.gpio_pin_expression(config[CONF_DIR_PIN]) | ||||
|     cg.add(var.set_dir_pin(dir_pin)) | ||||
|  | ||||
|     if CONF_SLEEP_PIN in config: | ||||
|         sleep_pin = yield cg.gpio_pin_expression(config[CONF_SLEEP_PIN]) | ||||
|         cg.add(var.set_sleep_pin(sleep_pin)) | ||||
|   | ||||
| @@ -6,9 +6,6 @@ namespace adc { | ||||
|  | ||||
| static const char *TAG = "adc"; | ||||
|  | ||||
| ADCSensor::ADCSensor(const std::string &name, uint8_t pin, uint32_t update_interval) | ||||
|     : PollingSensorComponent(name, update_interval), pin_(pin) {} | ||||
|  | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
| void ADCSensor::set_attenuation(adc_attenuation_t attenuation) { this->attenuation_ = attenuation; } | ||||
| #endif | ||||
|   | ||||
| @@ -7,11 +7,8 @@ | ||||
| namespace esphome { | ||||
| namespace adc { | ||||
|  | ||||
| class ADCSensor : public sensor::PollingSensorComponent { | ||||
| class ADCSensor : public sensor::Sensor, public PollingComponent { | ||||
|  public: | ||||
|   /// Construct the ADCSensor with the provided pin and update interval in ms. | ||||
|   explicit ADCSensor(const std::string &name, uint8_t pin, uint32_t update_interval); | ||||
|  | ||||
| #ifdef ARDUINO_ARCH_ESP32 | ||||
|   /// Set the attenuation for this pin. Only available on the ESP32. | ||||
|   void set_attenuation(adc_attenuation_t attenuation); | ||||
| @@ -26,6 +23,7 @@ class ADCSensor : public sensor::PollingSensorComponent { | ||||
|   void dump_config() override; | ||||
|   /// `HARDWARE_LATE` setup priority. | ||||
|   float get_setup_priority() const override; | ||||
|   void set_pin(uint8_t pin) { this->pin_ = pin; } | ||||
|  | ||||
| #ifdef ARDUINO_ARCH_ESP8266 | ||||
|   std::string unique_id() override; | ||||
|   | ||||
| @@ -2,8 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL, \ | ||||
|     CONF_ICON, ICON_FLASH, CONF_UNIT_OF_MEASUREMENT, UNIT_VOLT, CONF_ACCURACY_DECIMALS | ||||
| from esphome.const import CONF_ATTENUATION, CONF_ID, CONF_PIN, ICON_FLASH, UNIT_VOLT | ||||
|  | ||||
| ATTENUATION_MODES = { | ||||
|     '0db': cg.global_ns.ADC_0db, | ||||
| @@ -23,30 +22,24 @@ def validate_adc_pin(value): | ||||
| adc_ns = cg.esphome_ns.namespace('adc') | ||||
| ADCSensor = adc_ns.class_('ADCSensor', sensor.PollingSensorComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ADCSensor), | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 2).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ADCSensor), | ||||
|     cv.Required(CONF_PIN): validate_adc_pin, | ||||
|     cv.Optional(CONF_ATTENUATION): cv.All(cv.only_on_esp32, cv.one_of(*ATTENUATION_MODES, | ||||
|                                                                       lower=True)), | ||||
|  | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
|     cv.Optional(CONF_ICON, default=ICON_FLASH): sensor.icon, | ||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_VOLT): sensor.unit_of_measurement, | ||||
|     cv.Optional(CONF_ACCURACY_DECIMALS, default=2): sensor.accuracy_decimals, | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
|     cv.SplitDefault(CONF_ATTENUATION, esp32='0db'): | ||||
|         cv.All(cv.only_on_esp32, cv.enum(ATTENUATION_MODES, lower=True)), | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = config[CONF_PIN] | ||||
|     if pin == 'VCC': | ||||
|         pin = 0 | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|  | ||||
|     if config[CONF_PIN] == 'VCC': | ||||
|         cg.add_define('USE_ADC_SENSOR_VCC') | ||||
|         cg.add_global(cg.global_ns.ADC_MODE(cg.global_ns.ADC_VCC)) | ||||
|     rhs = ADCSensor.new(config[CONF_NAME], pin, config[CONF_UPDATE_INTERVAL]) | ||||
|     adc = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(adc, config) | ||||
|     yield sensor.register_sensor(adc, config) | ||||
|     else: | ||||
|         cg.add(var.set_pin(config[CONF_PIN])) | ||||
|  | ||||
|     if CONF_ATTENUATION in config: | ||||
|         cg.add(adc.set_attenuation(ATTENUATION_MODES[config[CONF_ATTENUATION]])) | ||||
|         cg.add(var.set_attenuation(config[CONF_ATTENUATION])) | ||||
|   | ||||
| @@ -11,7 +11,7 @@ ads1115_ns = cg.esphome_ns.namespace('ads1115') | ||||
| ADS1115Component = ads1115_ns.class_('ADS1115Component', cg.Component, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ADS1115Component), | ||||
|     cv.GenerateID(): cv.declare_id(ADS1115Component), | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(None)) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -48,9 +48,6 @@ class ADS1115Component : public Component, public i2c::I2CDevice { | ||||
| /// Internal holder class that is in instance of Sensor so that the hub can create individual sensors. | ||||
| class ADS1115Sensor : public sensor::Sensor { | ||||
|  public: | ||||
|   ADS1115Sensor(const std::string &name, uint32_t update_interval) | ||||
|       : sensor::Sensor(name), update_interval_(update_interval) {} | ||||
|  | ||||
|   void set_multiplexer(ADS1115Multiplexer multiplexer); | ||||
|   void set_gain(ADS1115Gain gain); | ||||
|  | ||||
|   | ||||
| @@ -2,8 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.components.ads1115 import ADS1115Component | ||||
| from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, CONF_UPDATE_INTERVAL, \ | ||||
|     ICON_FLASH, UNIT_VOLT, CONF_ID, CONF_NAME | ||||
| from esphome.const import CONF_GAIN, CONF_MULTIPLEXER, ICON_FLASH, UNIT_VOLT, CONF_ID | ||||
| from esphome.py_compat import string_types | ||||
| from . import ads1115_ns | ||||
|  | ||||
| @@ -38,27 +37,26 @@ def validate_gain(value): | ||||
|     elif not isinstance(value, string_types): | ||||
|         raise cv.Invalid('invalid gain "{}"'.format(value)) | ||||
|  | ||||
|     return cv.one_of(*GAIN)(value) | ||||
|     return cv.enum(GAIN)(value) | ||||
|  | ||||
|  | ||||
| ADS1115Sensor = ads1115_ns.class_('ADS1115Sensor', sensor.Sensor) | ||||
|  | ||||
|  | ||||
| CONF_ADS1115_ID = 'ads1115_id' | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ADS1115Sensor), | ||||
|     cv.GenerateID(CONF_ADS1115_ID): cv.use_variable_id(ADS1115Component), | ||||
|     cv.Required(CONF_MULTIPLEXER): cv.one_of(*MUX, upper=True, space='_'), | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 3).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ADS1115Sensor), | ||||
|     cv.GenerateID(CONF_ADS1115_ID): cv.use_id(ADS1115Component), | ||||
|     cv.Required(CONF_MULTIPLEXER): cv.enum(MUX, upper=True, space='_'), | ||||
|     cv.Required(CONF_GAIN): validate_gain, | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| })) | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     hub = yield cg.get_variable(config[CONF_ADS1115_ID]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL]) | ||||
|     cg.add(var.set_multiplexer(MUX[config[CONF_MULTIPLEXER]])) | ||||
|     cg.add(var.set_gain(GAIN[config[CONF_GAIN]])) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|  | ||||
|     cg.add(var.set_multiplexer(config[CONF_MULTIPLEXER])) | ||||
|     cg.add(var.set_gain(config[CONF_GAIN])) | ||||
|  | ||||
|     hub = yield cg.get_variable(config[CONF_ADS1115_ID]) | ||||
|     cg.add(hub.register_sensor(var)) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c | ||||
| from esphome.const import CONF_ID, CONF_UPDATE_INTERVAL | ||||
| from esphome.const import CONF_ID | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| AUTO_LOAD = ['sensor', 'binary_sensor'] | ||||
| @@ -13,12 +13,11 @@ apds9960_nds = cg.esphome_ns.namespace('apds9960') | ||||
| APDS9960 = apds9960_nds.class_('APDS9960', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(APDS9960), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x39)) | ||||
|     cv.GenerateID(): cv.declare_id(APDS9960), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x39)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|   | ||||
| @@ -10,7 +10,6 @@ namespace apds9960 { | ||||
|  | ||||
| class APDS9960 : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   APDS9960(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override; | ||||
|   | ||||
| @@ -13,11 +13,11 @@ DIRECTIONS = { | ||||
|     'RIGHT': 'set_right_direction', | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.Required(CONF_DIRECTION): cv.one_of(*DIRECTIONS, upper=True), | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_variable_id(APDS9960), | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
|     cv.Optional(CONF_DEVICE_CLASS, default=DEVICE_CLASS_MOVING): binary_sensor.device_class, | ||||
| })) | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_TYPE, CONF_UNIT_OF_MEASUREMENT, CONF_ACCURACY_DECIMALS, CONF_ICON, \ | ||||
|     UNIT_PERCENT, ICON_LIGHTBULB | ||||
| from esphome.const import CONF_TYPE, UNIT_PERCENT, ICON_LIGHTBULB | ||||
| from . import APDS9960, CONF_APDS9960_ID | ||||
|  | ||||
| DEPENDENCIES = ['apds9960'] | ||||
| @@ -15,14 +14,10 @@ TYPES = { | ||||
|     'PROXIMITY': 'set_proximity', | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_LIGHTBULB, 1).extend({ | ||||
|     cv.Required(CONF_TYPE): cv.one_of(*TYPES, upper=True), | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_variable_id(APDS9960), | ||||
|  | ||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_PERCENT): sensor.unit_of_measurement, | ||||
|     cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals, | ||||
|     cv.Optional(CONF_ICON, default=ICON_LIGHTBULB): sensor.icon, | ||||
| })) | ||||
|     cv.GenerateID(CONF_APDS9960_ID): cv.use_id(APDS9960), | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -1,20 +1,21 @@ | ||||
|  | ||||
| from esphome import automation | ||||
| from esphome.automation import ACTION_REGISTRY, CONDITION_REGISTRY, Condition | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import Condition | ||||
| from esphome.const import CONF_DATA, CONF_DATA_TEMPLATE, CONF_ID, CONF_PASSWORD, CONF_PORT, \ | ||||
|     CONF_REBOOT_TIMEOUT, CONF_SERVICE, CONF_VARIABLES, CONF_SERVICES, CONF_TRIGGER_ID | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| DEPENDENCIES = ['network'] | ||||
|  | ||||
| api_ns = cg.esphome_ns.namespace('api') | ||||
| APIServer = api_ns.class_('APIServer', cg.Component, cg.Controller) | ||||
| HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', cg.Action) | ||||
| HomeAssistantServiceCallAction = api_ns.class_('HomeAssistantServiceCallAction', automation.Action) | ||||
| KeyValuePair = api_ns.class_('KeyValuePair') | ||||
| TemplatableKeyValuePair = api_ns.class_('TemplatableKeyValuePair') | ||||
| APIConnectedCondition = api_ns.class_('APIConnectedCondition', Condition) | ||||
|  | ||||
| UserService = api_ns.class_('UserService', cg.Trigger) | ||||
| UserService = api_ns.class_('UserService', automation.Trigger) | ||||
| ServiceTypeArgument = api_ns.class_('ServiceTypeArgument') | ||||
| ServiceArgType = api_ns.enum('ServiceArgType') | ||||
| SERVICE_ARG_TYPES = { | ||||
| @@ -30,14 +31,13 @@ SERVICE_ARG_NATIVE_TYPES = { | ||||
|     'string': cg.std_string, | ||||
| } | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(APIServer), | ||||
|     cv.GenerateID(): cv.declare_id(APIServer), | ||||
|     cv.Optional(CONF_PORT, default=6053): cv.port, | ||||
|     cv.Optional(CONF_PASSWORD, default=''): cv.string_strict, | ||||
|     cv.Optional(CONF_REBOOT_TIMEOUT, default='5min'): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_SERVICES): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(UserService), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(UserService), | ||||
|         cv.Required(CONF_SERVICE): cv.valid_name, | ||||
|         cv.Optional(CONF_VARIABLES, default={}): cv.Schema({ | ||||
|             cv.validate_id_name: cv.one_of(*SERVICE_ARG_TYPES, lower=True), | ||||
| @@ -48,13 +48,12 @@ CONFIG_SCHEMA = cv.Schema({ | ||||
|  | ||||
| @coroutine_with_priority(40.0) | ||||
| def to_code(config): | ||||
|     rhs = APIServer.new() | ||||
|     api = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(api, config) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|  | ||||
|     cg.add(api.set_port(config[CONF_PORT])) | ||||
|     cg.add(api.set_password(config[CONF_PASSWORD])) | ||||
|     cg.add(api.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) | ||||
|     cg.add(var.set_port(config[CONF_PORT])) | ||||
|     cg.add(var.set_password(config[CONF_PASSWORD])) | ||||
|     cg.add(var.set_reboot_timeout(config[CONF_REBOOT_TIMEOUT])) | ||||
|  | ||||
|     for conf in config.get(CONF_SERVICES, []): | ||||
|         template_args = [] | ||||
| @@ -65,10 +64,9 @@ def to_code(config): | ||||
|             template_args.append(native) | ||||
|             func_args.append((native, name)) | ||||
|             service_type_args.append(ServiceTypeArgument(name, SERVICE_ARG_TYPES[var_])) | ||||
|         func = api.make_user_service_trigger.template(*template_args) | ||||
|         rhs = func(conf[CONF_SERVICE], service_type_args) | ||||
|         type_ = UserService.template(*template_args) | ||||
|         trigger = cg.Pvariable(conf[CONF_TRIGGER_ID], rhs, type=type_) | ||||
|         templ = cg.TemplateArguments(*template_args) | ||||
|         trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], templ, | ||||
|                                    conf[CONF_SERVICE], service_type_args) | ||||
|         yield automation.build_automation(trigger, func_args, conf) | ||||
|  | ||||
|     cg.add_define('USE_API') | ||||
| @@ -78,9 +76,8 @@ def to_code(config): | ||||
|         cg.add_library('ESPAsyncTCP', '1.2.0') | ||||
|  | ||||
|  | ||||
| CONF_HOMEASSISTANT_SERVICE = 'homeassistant.service' | ||||
| HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.use_variable_id(APIServer), | ||||
|     cv.GenerateID(): cv.use_id(APIServer), | ||||
|     cv.Required(CONF_SERVICE): cv.string, | ||||
|     cv.Optional(CONF_DATA): cv.Schema({ | ||||
|         cv.string: cv.string, | ||||
| @@ -94,34 +91,27 @@ HOMEASSISTANT_SERVICE_ACTION_SCHEMA = cv.Schema({ | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register(CONF_HOMEASSISTANT_SERVICE, HOMEASSISTANT_SERVICE_ACTION_SCHEMA) | ||||
| @automation.register_action('homeassistant.service', HomeAssistantServiceCallAction, | ||||
|                             HOMEASSISTANT_SERVICE_ACTION_SCHEMA) | ||||
| def homeassistant_service_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = HomeAssistantServiceCallAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     act = cg.Pvariable(action_id, rhs, type=type) | ||||
|     cg.add(act.set_service(config[CONF_SERVICE])) | ||||
|     serv = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, serv) | ||||
|     cg.add(var.set_service(config[CONF_SERVICE])) | ||||
|     if CONF_DATA in config: | ||||
|         datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA].items()] | ||||
|         cg.add(act.set_data(datas)) | ||||
|         cg.add(var.set_data(datas)) | ||||
|     if CONF_DATA_TEMPLATE in config: | ||||
|         datas = [KeyValuePair(k, v) for k, v in config[CONF_DATA_TEMPLATE].items()] | ||||
|         cg.add(act.set_data_template(datas)) | ||||
|         cg.add(var.set_data_template(datas)) | ||||
|     if CONF_VARIABLES in config: | ||||
|         datas = [] | ||||
|         for key, value in config[CONF_VARIABLES].items(): | ||||
|             value_ = yield cg.process_lambda(value, []) | ||||
|             datas.append(TemplatableKeyValuePair(key, value_)) | ||||
|         cg.add(act.set_variables(datas)) | ||||
|     yield act | ||||
|         cg.add(var.set_variables(datas)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| CONF_API_CONNECTED = 'api.connected' | ||||
| API_CONNECTED_CONDITION_SCHEMA = cv.Schema({}) | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register(CONF_API_CONNECTED, API_CONNECTED_CONDITION_SCHEMA) | ||||
| @automation.register_condition('api.connected', APIConnectedCondition, {}) | ||||
| def api_connected_to_code(config, condition_id, template_arg, args): | ||||
|     rhs = APIConnectedCondition.new(template_arg) | ||||
|     type = APIConnectedCondition.template(template_arg) | ||||
|     yield cg.Pvariable(condition_id, rhs, type=type) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg) | ||||
|   | ||||
| @@ -999,7 +999,7 @@ bool APIConnection::send_log_message(int level, const char *tag, const char *lin | ||||
|   bool success = this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE); | ||||
|  | ||||
|   if (!success) { | ||||
|     auto buffer = this->get_buffer(); | ||||
|     buffer = this->get_buffer(); | ||||
|     // bool send_failed = 4; | ||||
|     buffer.encode_bool(4, true); | ||||
|     return this->send_buffer(APIMessageType::SUBSCRIBE_LOGS_RESPONSE); | ||||
|   | ||||
| @@ -226,10 +226,7 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts | ||||
|     this->resp_.set_data_template(data_template); | ||||
|   } | ||||
|   void set_variables(const std::vector<TemplatableKeyValuePair> &variables) { this->resp_.set_variables(variables); } | ||||
|   void play(Ts... x) override { | ||||
|     this->parent_->send_service_call(this->resp_); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->parent_->send_service_call(this->resp_); } | ||||
|  | ||||
|  protected: | ||||
|   APIServer *parent_; | ||||
|   | ||||
| @@ -138,11 +138,8 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa | ||||
|   this->supports_away_ = true; | ||||
|   this->away_config_ = away_config; | ||||
| } | ||||
| BangBangClimate::BangBangClimate(const std::string &name) | ||||
|     : climate::Climate(name), | ||||
|       idle_trigger_(new Trigger<>()), | ||||
|       cool_trigger_(new Trigger<>()), | ||||
|       heat_trigger_(new Trigger<>()) {} | ||||
| BangBangClimate::BangBangClimate() | ||||
|     : idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {} | ||||
| void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; } | ||||
| Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; } | ||||
| Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; } | ||||
|   | ||||
| @@ -19,7 +19,7 @@ struct BangBangClimateTargetTempConfig { | ||||
|  | ||||
| class BangBangClimate : public climate::Climate, public Component { | ||||
|  public: | ||||
|   BangBangClimate(const std::string &name); | ||||
|   BangBangClimate(); | ||||
|   void setup() override; | ||||
|  | ||||
|   void set_sensor(sensor::Sensor *sensor); | ||||
|   | ||||
| @@ -4,15 +4,15 @@ from esphome import automation | ||||
| from esphome.components import climate, sensor | ||||
| from esphome.const import CONF_AWAY_CONFIG, CONF_COOL_ACTION, \ | ||||
|     CONF_DEFAULT_TARGET_TEMPERATURE_HIGH, CONF_DEFAULT_TARGET_TEMPERATURE_LOW, CONF_HEAT_ACTION, \ | ||||
|     CONF_ID, CONF_IDLE_ACTION, CONF_NAME, CONF_SENSOR | ||||
|     CONF_ID, CONF_IDLE_ACTION, CONF_SENSOR | ||||
|  | ||||
| bang_bang_ns = cg.esphome_ns.namespace('bang_bang') | ||||
| BangBangClimate = bang_bang_ns.class_('BangBangClimate', climate.ClimateDevice) | ||||
| BangBangClimateTargetTempConfig = bang_bang_ns.struct('BangBangClimateTargetTempConfig') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(climate.CLIMATE_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BangBangClimate), | ||||
|     cv.Required(CONF_SENSOR): cv.use_variable_id(sensor.Sensor), | ||||
| CONFIG_SCHEMA = cv.All(climate.CLIMATE_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BangBangClimate), | ||||
|     cv.Required(CONF_SENSOR): cv.use_id(sensor.Sensor), | ||||
|     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_LOW): cv.temperature, | ||||
|     cv.Required(CONF_DEFAULT_TARGET_TEMPERATURE_HIGH): cv.temperature, | ||||
|     cv.Required(CONF_IDLE_ACTION): automation.validate_automation(single=True), | ||||
| @@ -26,7 +26,7 @@ CONFIG_SCHEMA = cv.nameable(climate.CLIMATE_SCHEMA.extend({ | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield climate.register_climate(var, config) | ||||
|  | ||||
|   | ||||
| @@ -8,9 +8,6 @@ static const char *TAG = "bh1750.sensor"; | ||||
|  | ||||
| static const uint8_t BH1750_COMMAND_POWER_ON = 0b00000001; | ||||
|  | ||||
| BH1750Sensor::BH1750Sensor(const std::string &name, uint32_t update_interval) | ||||
|     : PollingSensorComponent(name, update_interval) {} | ||||
|  | ||||
| void BH1750Sensor::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up BH1750 '%s'...", this->name_.c_str()); | ||||
|   if (!this->write_bytes(BH1750_COMMAND_POWER_ON, nullptr, 0)) { | ||||
|   | ||||
| @@ -15,10 +15,8 @@ enum BH1750Resolution { | ||||
| }; | ||||
|  | ||||
| /// This class implements support for the i2c-based BH1750 ambient light sensor. | ||||
| class BH1750Sensor : public sensor::PollingSensorComponent, public i2c::I2CDevice { | ||||
| class BH1750Sensor : public sensor::Sensor, public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   BH1750Sensor(const std::string &name, uint32_t update_interval); | ||||
|  | ||||
|   /** Set the resolution of this sensor. | ||||
|    * | ||||
|    * Possible values are: | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_NAME, CONF_RESOLUTION, CONF_UPDATE_INTERVAL, UNIT_LUX, \ | ||||
|     ICON_BRIGHTNESS_5 | ||||
| from esphome.const import CONF_ID, CONF_RESOLUTION, UNIT_LUX, ICON_BRIGHTNESS_5 | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
|  | ||||
| @@ -16,17 +15,16 @@ BH1750_RESOLUTIONS = { | ||||
|  | ||||
| BH1750Sensor = bh1750_ns.class_('BH1750Sensor', sensor.PollingSensorComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BH1750Sensor), | ||||
|     cv.Optional(CONF_RESOLUTION, default=0.0): cv.one_of(*BH1750_RESOLUTIONS, float=True), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x23))) | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_LUX, ICON_BRIGHTNESS_5, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BH1750Sensor), | ||||
|     cv.Optional(CONF_RESOLUTION, default=0.5): cv.enum(BH1750_RESOLUTIONS, float=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x23)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
|     cg.add(var.set_resolution(BH1750_RESOLUTIONS[config[CONF_RESOLUTION]])) | ||||
|     cg.add(var.set_resolution(config[CONF_RESOLUTION])) | ||||
|   | ||||
| @@ -1,25 +1,27 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import fan, output | ||||
| from esphome.const import CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, \ | ||||
|     CONF_OUTPUT_ID | ||||
| from esphome.const import CONF_OSCILLATION_OUTPUT, CONF_OUTPUT, CONF_OUTPUT_ID | ||||
| from .. import binary_ns | ||||
|  | ||||
| BinaryFan = binary_ns.class_('BinaryFan', cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(fan.FAN_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(BinaryFan), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput), | ||||
|     cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_variable_id(output.BinaryOutput), | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| CONFIG_SCHEMA = fan.FAN_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryFan), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
|     cv.Optional(CONF_OSCILLATION_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     output_ = yield cg.get_variable(config[CONF_OUTPUT]) | ||||
|     state = yield fan.create_fan_state(config) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID], state, output_) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|  | ||||
|     fan_ = yield fan.create_fan_state(config) | ||||
|     cg.add(var.set_fan(fan_)) | ||||
|     output_ = yield cg.get_variable(config[CONF_OUTPUT]) | ||||
|     cg.add(var.set_output(output_)) | ||||
|  | ||||
|     if CONF_OSCILLATION_OUTPUT in config: | ||||
|         oscillation_output = yield cg.get_variable(config[CONF_OSCILLATION_OUTPUT]) | ||||
|         cg.add(var.set_oscillation(oscillation_output)) | ||||
|   | ||||
| @@ -9,7 +9,8 @@ namespace binary { | ||||
|  | ||||
| class BinaryFan : public Component { | ||||
|  public: | ||||
|   BinaryFan(fan::FanState *fan, output::BinaryOutput *output) : fan_(fan), output_(output) {} | ||||
|   void set_fan(fan::FanState *fan) { fan_ = fan; } | ||||
|   void set_output(output::BinaryOutput *output) { output_ = output; } | ||||
|   void setup() override; | ||||
|   void loop() override; | ||||
|   void dump_config() override; | ||||
|   | ||||
| @@ -6,13 +6,15 @@ from .. import binary_ns | ||||
|  | ||||
| BinaryLightOutput = binary_ns.class_('BinaryLightOutput', light.LightOutput) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(light.BINARY_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(BinaryLightOutput), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_variable_id(output.BinaryOutput), | ||||
| })) | ||||
| CONFIG_SCHEMA = light.BINARY_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(BinaryLightOutput), | ||||
|     cv.Required(CONF_OUTPUT): cv.use_id(output.BinaryOutput), | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     out = yield cg.get_variable(config[CONF_OUTPUT]) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID], out) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) | ||||
|     yield light.register_light(var, config) | ||||
|  | ||||
|     out = yield cg.get_variable(config[CONF_OUTPUT]) | ||||
|     cg.add(var.set_output(out)) | ||||
|   | ||||
| @@ -9,7 +9,7 @@ namespace binary { | ||||
|  | ||||
| class BinaryLightOutput : public light::LightOutput { | ||||
|  public: | ||||
|   BinaryLightOutput(output::BinaryOutput *output) : output_(output) {} | ||||
|   void set_output(output::BinaryOutput *output) { output_ = output; } | ||||
|   light::LightTraits get_traits() override { | ||||
|     auto traits = light::LightTraits(); | ||||
|     traits.set_supports_brightness(false); | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation, core | ||||
| from esphome.automation import CONDITION_REGISTRY, Condition, maybe_simple_id | ||||
| from esphome.automation import Condition, maybe_simple_id | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_DEVICE_CLASS, CONF_FILTERS, \ | ||||
|     CONF_ID, CONF_INTERNAL, CONF_INVALID_COOLDOWN, CONF_INVERTED, \ | ||||
|     CONF_MAX_LENGTH, CONF_MIN_LENGTH, CONF_ON_CLICK, \ | ||||
|     CONF_ON_DOUBLE_CLICK, CONF_ON_MULTI_CLICK, CONF_ON_PRESS, CONF_ON_RELEASE, CONF_ON_STATE, \ | ||||
|     CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_VALUE, CONF_NAME, CONF_MQTT_ID | ||||
|     CONF_STATE, CONF_TIMING, CONF_TRIGGER_ID, CONF_FOR, CONF_NAME, CONF_MQTT_ID | ||||
| from esphome.core import CORE, coroutine | ||||
| from esphome.py_compat import string_types | ||||
| from esphome.util import ServiceRegistry | ||||
| from esphome.util import Registry | ||||
|  | ||||
| DEVICE_CLASSES = [ | ||||
|     '', 'battery', 'cold', 'connectivity', 'door', 'garage_door', 'gas', | ||||
| @@ -26,15 +26,15 @@ BinarySensor = binary_sensor_ns.class_('BinarySensor', cg.Nameable) | ||||
| BinarySensorPtr = BinarySensor.operator('ptr') | ||||
|  | ||||
| # Triggers | ||||
| PressTrigger = binary_sensor_ns.class_('PressTrigger', cg.Trigger.template()) | ||||
| ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', cg.Trigger.template()) | ||||
| ClickTrigger = binary_sensor_ns.class_('ClickTrigger', cg.Trigger.template()) | ||||
| DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', cg.Trigger.template()) | ||||
| MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', cg.Trigger.template(), | ||||
| PressTrigger = binary_sensor_ns.class_('PressTrigger', automation.Trigger.template()) | ||||
| ReleaseTrigger = binary_sensor_ns.class_('ReleaseTrigger', automation.Trigger.template()) | ||||
| ClickTrigger = binary_sensor_ns.class_('ClickTrigger', automation.Trigger.template()) | ||||
| DoubleClickTrigger = binary_sensor_ns.class_('DoubleClickTrigger', automation.Trigger.template()) | ||||
| MultiClickTrigger = binary_sensor_ns.class_('MultiClickTrigger', automation.Trigger.template(), | ||||
|                                             cg.Component) | ||||
| MultiClickTriggerEvent = binary_sensor_ns.struct('MultiClickTriggerEvent') | ||||
| StateTrigger = binary_sensor_ns.class_('StateTrigger', cg.Trigger.template(bool)) | ||||
| BinarySensorPublishAction = binary_sensor_ns.class_('BinarySensorPublishAction', cg.Action) | ||||
| StateTrigger = binary_sensor_ns.class_('StateTrigger', automation.Trigger.template(bool)) | ||||
| BinarySensorPublishAction = binary_sensor_ns.class_('BinarySensorPublishAction', automation.Action) | ||||
|  | ||||
| # Condition | ||||
| BinarySensorCondition = binary_sensor_ns.class_('BinarySensorCondition', Condition) | ||||
| @@ -46,55 +46,34 @@ DelayedOffFilter = binary_sensor_ns.class_('DelayedOffFilter', Filter, cg.Compon | ||||
| InvertFilter = binary_sensor_ns.class_('InvertFilter', Filter) | ||||
| LambdaFilter = binary_sensor_ns.class_('LambdaFilter', Filter) | ||||
|  | ||||
| FILTER_REGISTRY = ServiceRegistry() | ||||
| validate_filters = cv.validate_registry('filter', FILTER_REGISTRY, [CONF_ID]) | ||||
| FILTER_REGISTRY = Registry() | ||||
| validate_filters = cv.validate_registry('filter', FILTER_REGISTRY) | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('invert', | ||||
|                           cv.Schema({ | ||||
|                               cv.GenerateID(): cv.declare_variable_id(InvertFilter) | ||||
|                           })) | ||||
| def invert_filter_to_code(config): | ||||
|     rhs = InvertFilter.new() | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
| @FILTER_REGISTRY.register('invert', InvertFilter, {}) | ||||
| def invert_filter_to_code(config, filter_id): | ||||
|     yield cg.new_Pvariable(filter_id) | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_on', DelayedOnFilter, | ||||
|                           cv.positive_time_period_milliseconds) | ||||
| def delayed_on_filter_to_code(config, filter_id): | ||||
|     var = cg.new_Pvariable(filter_id, config) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_on', | ||||
|                           cv.maybe_simple_value(cv.Schema({ | ||||
|                               cv.GenerateID(): cv.declare_variable_id(DelayedOnFilter), | ||||
|                               cv.Required(CONF_VALUE): cv.positive_time_period_milliseconds, | ||||
|                           }).extend(cv.COMPONENT_SCHEMA))) | ||||
| def delayed_on_filter_to_code(config): | ||||
|     rhs = DelayedOnFilter.new(config[CONF_VALUE]) | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(var, config) | ||||
| @FILTER_REGISTRY.register('delayed_off', DelayedOffFilter, cv.positive_time_period_milliseconds) | ||||
| def delayed_off_filter_to_code(config, filter_id): | ||||
|     var = cg.new_Pvariable(filter_id, config) | ||||
|     yield cg.register_component(var, {}) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('delayed_off', | ||||
|                           cv.maybe_simple_value(cv.Schema({ | ||||
|                               cv.GenerateID(): cv.declare_variable_id(DelayedOffFilter), | ||||
|                               cv.Required(CONF_VALUE): cv.positive_time_period_milliseconds, | ||||
|                           }).extend(cv.COMPONENT_SCHEMA))) | ||||
| def delayed_off_filter_to_code(config): | ||||
|     rhs = DelayedOffFilter.new(config[CONF_VALUE]) | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @FILTER_REGISTRY.register('lambda', | ||||
|                           cv.maybe_simple_value(cv.Schema({ | ||||
|                               cv.GenerateID(): cv.declare_variable_id(LambdaFilter), | ||||
|                               cv.Required(CONF_VALUE): cv.lambda_, | ||||
|                           }))) | ||||
| def lambda_filter_to_code(config): | ||||
|     lambda_ = yield cg.process_lambda(config[CONF_VALUE], [(bool, 'x')], | ||||
|                                       return_type=cg.optional.template(bool)) | ||||
|     rhs = LambdaFilter.new(lambda_) | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield var | ||||
| @FILTER_REGISTRY.register('lambda', LambdaFilter, cv.lambda_) | ||||
| def lambda_filter_to_code(config, filter_id): | ||||
|     lambda_ = yield cg.process_lambda(config, [(bool, 'x')], return_type=cg.optional.template(bool)) | ||||
|     yield cg.new_Pvariable(filter_id, lambda_) | ||||
|  | ||||
|  | ||||
| MULTI_CLICK_TIMING_SCHEMA = cv.Schema({ | ||||
| @@ -193,35 +172,35 @@ def validate_multi_click_timing(value): | ||||
| device_class = cv.one_of(*DEVICE_CLASSES, lower=True, space='_') | ||||
|  | ||||
| BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BinarySensor), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTBinarySensorComponent), | ||||
|     cv.GenerateID(): cv.declare_id(BinarySensor), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTBinarySensorComponent), | ||||
|  | ||||
|     cv.Optional(CONF_DEVICE_CLASS): device_class, | ||||
|     cv.Optional(CONF_FILTERS): validate_filters, | ||||
|     cv.Optional(CONF_ON_PRESS): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(PressTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PressTrigger), | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_RELEASE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ReleaseTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ReleaseTrigger), | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(ClickTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClickTrigger), | ||||
|         cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_DOUBLE_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(DoubleClickTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DoubleClickTrigger), | ||||
|         cv.Optional(CONF_MIN_LENGTH, default='50ms'): cv.positive_time_period_milliseconds, | ||||
|         cv.Optional(CONF_MAX_LENGTH, default='350ms'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_MULTI_CLICK): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(MultiClickTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(MultiClickTrigger), | ||||
|         cv.Required(CONF_TIMING): cv.All([parse_multi_click_timing_str], | ||||
|                                          validate_multi_click_timing), | ||||
|         cv.Optional(CONF_INVALID_COOLDOWN, default='1s'): cv.positive_time_period_milliseconds, | ||||
|     }), | ||||
|     cv.Optional(CONF_ON_STATE): automation.validate_automation({ | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_variable_id(StateTrigger), | ||||
|         cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), | ||||
|     }), | ||||
|  | ||||
|     cv.Optional(CONF_INVERTED): cv.invalid( | ||||
| @@ -234,6 +213,7 @@ BINARY_SENSOR_SCHEMA = cv.MQTT_COMPONENT_SCHEMA.extend({ | ||||
|  | ||||
| @coroutine | ||||
| def setup_binary_sensor_core_(var, config): | ||||
|     cg.add(var.set_name(config[CONF_NAME])) | ||||
|     if CONF_INTERNAL in config: | ||||
|         cg.add(var.set_internal(CONF_INTERNAL)) | ||||
|     if CONF_DEVICE_CLASS in config: | ||||
| @@ -300,26 +280,24 @@ def new_binary_sensor(config): | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(BinarySensor), | ||||
| BINARY_SENSOR_CONDITION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(BinarySensor), | ||||
|     cv.Optional(CONF_FOR): cv.positive_time_period_milliseconds, | ||||
| }) | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register('binary_sensor.is_on', BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA) | ||||
| @automation.register_condition('binary_sensor.is_on', BinarySensorCondition, | ||||
|                                BINARY_SENSOR_CONDITION_SCHEMA) | ||||
| def binary_sensor_is_on_to_code(config, condition_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = BinarySensorCondition.template(template_arg) | ||||
|     rhs = type.new(var, True, config.get(CONF_FOR)) | ||||
|     yield cg.Pvariable(condition_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, paren, True, config.get(CONF_FOR)) | ||||
|  | ||||
|  | ||||
| @CONDITION_REGISTRY.register('binary_sensor.is_off', BINARY_SENSOR_IS_ON_OFF_CONDITION_SCHEMA) | ||||
| @automation.register_condition('binary_sensor.is_off', BinarySensorCondition, | ||||
|                                BINARY_SENSOR_CONDITION_SCHEMA) | ||||
| def binary_sensor_is_off_to_code(config, condition_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = BinarySensorCondition.template(template_arg) | ||||
|     rhs = type.new(var, False, config.get(CONF_FOR)) | ||||
|     yield cg.Pvariable(condition_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(condition_id, template_arg, paren, False, config.get(CONF_FOR)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -150,7 +150,6 @@ template<typename... Ts> class BinarySensorPublishAction : public Action<Ts...> | ||||
|   void play(Ts... x) override { | ||||
|     auto val = this->state_.value(x...); | ||||
|     this->sensor_->publish_state(val); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   | ||||
| @@ -24,12 +24,12 @@ namespace binary_sensor { | ||||
|  */ | ||||
| class BinarySensor : public Nameable { | ||||
|  public: | ||||
|   explicit BinarySensor(); | ||||
|   /** Construct a binary sensor with the specified name | ||||
|    * | ||||
|    * @param name Name of this binary sensor. | ||||
|    */ | ||||
|   explicit BinarySensor(const std::string &name); | ||||
|   explicit BinarySensor(); | ||||
|  | ||||
|   /** Add a callback to be notified of state changes. | ||||
|    * | ||||
|   | ||||
| @@ -11,10 +11,10 @@ ble_presence_ns = cg.esphome_ns.namespace('ble_presence') | ||||
| BLEPresenceDevice = ble_presence_ns.class_('BLEPresenceDevice', binary_sensor.BinarySensor, | ||||
|                                            cg.Component, ESPBTDeviceListener) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BLEPresenceDevice), | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BLEPresenceDevice), | ||||
|     cv.Required(CONF_MAC_ADDRESS): cv.mac_address, | ||||
| }).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -3,8 +3,7 @@ import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.components.esp32_ble_tracker import CONF_ESP32_BLE_ID, ESPBTDeviceListener, \ | ||||
|     ESP_BLE_DEVICE_SCHEMA | ||||
| from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, CONF_UNIT_OF_MEASUREMENT, \ | ||||
|     CONF_ICON, CONF_ACCURACY_DECIMALS, UNIT_DECIBEL, ICON_SIGNAL | ||||
| from esphome.const import CONF_MAC_ADDRESS, CONF_NAME, CONF_ID, UNIT_DECIBEL, ICON_SIGNAL | ||||
|  | ||||
| DEPENDENCIES = ['esp32_ble_tracker'] | ||||
|  | ||||
| @@ -12,14 +11,10 @@ ble_rssi_ns = cg.esphome_ns.namespace('ble_rssi') | ||||
| BLERSSISensor = ble_rssi_ns.class_('BLERSSISensor', sensor.Sensor, cg.Component, | ||||
|                                    ESPBTDeviceListener) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BLERSSISensor), | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_DECIBEL, ICON_SIGNAL, 0).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(BLERSSISensor), | ||||
|     cv.Required(CONF_MAC_ADDRESS): cv.mac_address, | ||||
|  | ||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_DECIBEL): sensor.unit_of_measurement, | ||||
|     cv.Optional(CONF_ICON, default=ICON_SIGNAL): sensor.icon, | ||||
|     cv.Optional(CONF_ACCURACY_DECIMALS, default=0): sensor.accuracy_decimals | ||||
| }).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(ESP_BLE_DEVICE_SCHEMA).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -60,8 +60,6 @@ enum BME280IIRFilter { | ||||
| /// This class implements support for the BME280 Temperature+Pressure+Humidity i2c sensor. | ||||
| class BME280Component : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   BME280Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
|   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } | ||||
|   void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } | ||||
|   void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, \ | ||||
|     CONF_PRESSURE, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, ICON_THERMOMETER, \ | ||||
|     CONF_PRESSURE, CONF_TEMPERATURE, ICON_THERMOMETER, \ | ||||
|     UNIT_CELSIUS, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| @@ -30,29 +30,28 @@ IIR_FILTER_OPTIONS = { | ||||
| BME280Component = bme280_ns.class_('BME280Component', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BME280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): cv.nameable( | ||||
|     cv.GenerateID(): cv.declare_id(BME280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_PRESSURE): cv.nameable( | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_PRESSURE): | ||||
|         sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_HUMIDITY): cv.nameable( | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_HUMIDITY): | ||||
|         sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77)) | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
| @@ -60,18 +59,18 @@ def to_code(config): | ||||
|         conf = config[CONF_TEMPERATURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_temperature_sensor(sens)) | ||||
|         cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_PRESSURE in config: | ||||
|         conf = config[CONF_PRESSURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_pressure_sensor(sens)) | ||||
|         cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_HUMIDITY in config: | ||||
|         conf = config[CONF_HUMIDITY] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_humidity_sensor(sens)) | ||||
|         cg.add(var.set_humidity_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_humidity_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     cg.add(var.set_iir_filter(IIR_FILTER_OPTIONS[config[CONF_IIR_FILTER]])) | ||||
|     cg.add(var.set_iir_filter(config[CONF_IIR_FILTER])) | ||||
|   | ||||
| @@ -68,8 +68,6 @@ struct BME680CalibrationData { | ||||
|  | ||||
| class BME680Component : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   BME680Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
|   /// Set the temperature oversampling value. Defaults to 16X. | ||||
|   void set_temperature_oversampling(BME680Oversampling temperature_oversampling); | ||||
|   /// Set the pressure oversampling value. Defaults to 16X. | ||||
|   | ||||
| @@ -4,7 +4,7 @@ from esphome import core | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_DURATION, CONF_GAS_RESISTANCE, CONF_HEATER, \ | ||||
|     CONF_HUMIDITY, CONF_ID, CONF_IIR_FILTER, CONF_OVERSAMPLING, CONF_PRESSURE, \ | ||||
|     CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, UNIT_OHM, ICON_GAS_CYLINDER, UNIT_CELSIUS, \ | ||||
|     CONF_TEMPERATURE, UNIT_OHM, ICON_GAS_CYLINDER, UNIT_CELSIUS, \ | ||||
|     ICON_THERMOMETER, UNIT_HECTOPASCAL, ICON_GAUGE, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| @@ -35,36 +35,35 @@ IIR_FILTER_OPTIONS = { | ||||
| BME680Component = bme680_ns.class_('BME680Component', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BME680Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): cv.nameable( | ||||
|     cv.GenerateID(): cv.declare_id(BME680Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_PRESSURE): cv.nameable( | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_PRESSURE): | ||||
|         sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_HUMIDITY): cv.nameable( | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_HUMIDITY): | ||||
|         sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_GAS_RESISTANCE): cv.nameable( | ||||
|         sensor.sensor_schema(UNIT_OHM, ICON_GAS_CYLINDER, 1)), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True), | ||||
|                 cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|         }), | ||||
|     cv.Optional(CONF_GAS_RESISTANCE): | ||||
|         sensor.sensor_schema(UNIT_OHM, ICON_GAS_CYLINDER, 1), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
|     cv.Optional(CONF_HEATER): cv.Any(None, cv.All(cv.Schema({ | ||||
|         cv.Optional(CONF_TEMPERATURE, default=320): cv.All(cv.Coerce(int), cv.Range(200, 400)), | ||||
|         cv.Optional(CONF_TEMPERATURE, default=320): cv.int_range(min=200, max=400), | ||||
|         cv.Optional(CONF_DURATION, default='150ms'): cv.All( | ||||
|             cv.positive_time_period_milliseconds, cv.Range(max=core.TimePeriod(milliseconds=4032))) | ||||
|     }, cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION)))), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x76)) | ||||
|     }), cv.has_at_least_one_key(CONF_TEMPERATURE, CONF_DURATION))), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x76)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
| @@ -72,19 +71,19 @@ def to_code(config): | ||||
|         conf = config[CONF_TEMPERATURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_temperature_sensor(sens)) | ||||
|         cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_PRESSURE in config: | ||||
|         conf = config[CONF_PRESSURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_pressure_sensor(sens)) | ||||
|         cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_HUMIDITY in config: | ||||
|         conf = config[CONF_HUMIDITY] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_humidity_sensor(sens)) | ||||
|         cg.add(var.set_humidity_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_humidity_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_GAS_RESISTANCE in config: | ||||
|         conf = config[CONF_GAS_RESISTANCE] | ||||
|   | ||||
| @@ -9,8 +9,6 @@ namespace bmp085 { | ||||
|  | ||||
| class BMP085Component : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   BMP085Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
|   void set_temperature(sensor::Sensor *temperature) { temperature_ = temperature; } | ||||
|   void set_pressure(sensor::Sensor *pressure) { pressure_ = pressure; } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \ | ||||
|     CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL | ||||
|     UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
|  | ||||
| @@ -10,17 +10,14 @@ bmp085_ns = cg.esphome_ns.namespace('bmp085') | ||||
| BMP085Component = bmp085_ns.class_('BMP085Component', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BMP085Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         cv.nameable(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1)), | ||||
|     cv.Optional(CONF_PRESSURE): | ||||
|         cv.nameable(sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1)), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77)) | ||||
|     cv.GenerateID(): cv.declare_id(BMP085Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1), | ||||
|     cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
|   | ||||
| @@ -233,7 +233,6 @@ uint16_t BMP280Component::read_u16_le_(uint8_t a_register) { | ||||
|   return (data >> 8) | (data << 8); | ||||
| } | ||||
| int16_t BMP280Component::read_s16_le_(uint8_t a_register) { return this->read_u16_le_(a_register); } | ||||
| BMP280Component::BMP280Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
| }  // namespace bmp280 | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -53,7 +53,6 @@ enum BMP280IIRFilter { | ||||
| /// This class implements support for the BMP280 Temperature+Pressure i2c sensor. | ||||
| class BMP280Component : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   BMP280Component(uint32_t update_interval); | ||||
|   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } | ||||
|   void set_pressure_sensor(sensor::Sensor *pressure_sensor) { pressure_sensor_ = pressure_sensor; } | ||||
|  | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_ID, CONF_PRESSURE, CONF_TEMPERATURE, \ | ||||
|     CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL, \ | ||||
|     UNIT_CELSIUS, ICON_THERMOMETER, ICON_GAUGE, UNIT_HECTOPASCAL, \ | ||||
|     CONF_IIR_FILTER, CONF_OVERSAMPLING | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
| @@ -30,24 +30,19 @@ IIR_FILTER_OPTIONS = { | ||||
| BMP280Component = bmp280_ns.class_('BMP280Component', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(BMP280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): cv.nameable( | ||||
|         sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_PRESSURE): cv.nameable( | ||||
|         sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ | ||||
|             cv.Optional(CONF_OVERSAMPLING, default='16X'): | ||||
|                 cv.one_of(*OVERSAMPLING_OPTIONS, upper=True), | ||||
|         })), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.one_of(*IIR_FILTER_OPTIONS, upper=True), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x77)) | ||||
|     cv.GenerateID(): cv.declare_id(BMP280Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ | ||||
|         cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|     }), | ||||
|     cv.Optional(CONF_PRESSURE): sensor.sensor_schema(UNIT_HECTOPASCAL, ICON_GAUGE, 1).extend({ | ||||
|         cv.Optional(CONF_OVERSAMPLING, default='16X'): cv.enum(OVERSAMPLING_OPTIONS, upper=True), | ||||
|     }), | ||||
|     cv.Optional(CONF_IIR_FILTER, default='OFF'): cv.enum(IIR_FILTER_OPTIONS, upper=True), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x77)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
| @@ -55,10 +50,10 @@ def to_code(config): | ||||
|         conf = config[CONF_TEMPERATURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_temperature_sensor(sens)) | ||||
|         cg.add(var.set_temperature_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_temperature_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|  | ||||
|     if CONF_PRESSURE in config: | ||||
|         conf = config[CONF_PRESSURE] | ||||
|         sens = yield sensor.new_sensor(conf) | ||||
|         cg.add(var.set_pressure_sensor(sens)) | ||||
|         cg.add(var.set_pressure_oversampling(OVERSAMPLING_OPTIONS[conf[CONF_OVERSAMPLING]])) | ||||
|         cg.add(var.set_pressure_oversampling(conf[CONF_OVERSAMPLING])) | ||||
|   | ||||
| @@ -1,13 +1,15 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.automation import ACTION_REGISTRY | ||||
| from esphome import automation | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_AWAY, CONF_ID, CONF_INTERNAL, CONF_MAX_TEMPERATURE, \ | ||||
|     CONF_MIN_TEMPERATURE, CONF_MODE, CONF_TARGET_TEMPERATURE, \ | ||||
|     CONF_TARGET_TEMPERATURE_HIGH, CONF_TARGET_TEMPERATURE_LOW, CONF_TEMPERATURE_STEP, CONF_VISUAL, \ | ||||
|     CONF_MQTT_ID | ||||
|     CONF_MQTT_ID, CONF_NAME | ||||
| from esphome.core import CORE, coroutine | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
|  | ||||
| climate_ns = cg.esphome_ns.namespace('climate') | ||||
|  | ||||
| ClimateDevice = climate_ns.class_('Climate', cg.Nameable) | ||||
| @@ -23,14 +25,14 @@ CLIMATE_MODES = { | ||||
|     'HEAT': ClimateMode.CLIMATE_MODE_HEAT, | ||||
| } | ||||
|  | ||||
| validate_climate_mode = cv.one_of(*CLIMATE_MODES, upper=True) | ||||
| validate_climate_mode = cv.enum(CLIMATE_MODES, upper=True) | ||||
|  | ||||
| # Actions | ||||
| ControlAction = climate_ns.class_('ControlAction', cg.Action) | ||||
| ControlAction = climate_ns.class_('ControlAction', automation.Action) | ||||
|  | ||||
| CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ClimateDevice), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTClimateComponent), | ||||
|     cv.GenerateID(): cv.declare_id(ClimateDevice), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTClimateComponent), | ||||
|     cv.Optional(CONF_VISUAL, default={}): cv.Schema({ | ||||
|         cv.Optional(CONF_MIN_TEMPERATURE): cv.temperature, | ||||
|         cv.Optional(CONF_MAX_TEMPERATURE): cv.temperature, | ||||
| @@ -42,6 +44,7 @@ CLIMATE_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|  | ||||
| @coroutine | ||||
| def setup_climate_core_(var, config): | ||||
|     cg.add(var.set_name(config[CONF_NAME])) | ||||
|     if CONF_INTERNAL in config: | ||||
|         cg.add(var.set_internal(config[CONF_INTERNAL])) | ||||
|     visual = config[CONF_VISUAL] | ||||
| @@ -66,7 +69,7 @@ def register_climate(var, config): | ||||
|  | ||||
|  | ||||
| CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(ClimateDevice), | ||||
|     cv.Required(CONF_ID): cv.use_id(ClimateDevice), | ||||
|     cv.Optional(CONF_MODE): cv.templatable(validate_climate_mode), | ||||
|     cv.Optional(CONF_TARGET_TEMPERATURE): cv.templatable(cv.temperature), | ||||
|     cv.Optional(CONF_TARGET_TEMPERATURE_LOW): cv.templatable(cv.temperature), | ||||
| @@ -75,29 +78,26 @@ CLIMATE_CONTROL_ACTION_SCHEMA = cv.Schema({ | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('climate.control', CLIMATE_CONTROL_ACTION_SCHEMA) | ||||
| @automation.register_action('climate.control', ControlAction, CLIMATE_CONTROL_ACTION_SCHEMA) | ||||
| def climate_control_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = ControlAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     action = cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|     if CONF_MODE in config: | ||||
|         template_ = yield cg.templatable(config[CONF_MODE], args, ClimateMode, | ||||
|                                          to_exp=CLIMATE_MODES) | ||||
|         cg.add(action.set_mode(template_)) | ||||
|         template_ = yield cg.templatable(config[CONF_MODE], args, ClimateMode) | ||||
|         cg.add(var.set_mode(template_)) | ||||
|     if CONF_TARGET_TEMPERATURE in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE], args, float) | ||||
|         cg.add(action.set_target_temperature(template_)) | ||||
|         cg.add(var.set_target_temperature(template_)) | ||||
|     if CONF_TARGET_TEMPERATURE_LOW in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_LOW], args, float) | ||||
|         cg.add(action.set_target_temperature_low(template_)) | ||||
|         cg.add(var.set_target_temperature_low(template_)) | ||||
|     if CONF_TARGET_TEMPERATURE_HIGH in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TARGET_TEMPERATURE_HIGH], args, float) | ||||
|         cg.add(action.set_target_temperature_high(template_)) | ||||
|         cg.add(var.set_target_temperature_high(template_)) | ||||
|     if CONF_AWAY in config: | ||||
|         template_ = yield cg.templatable(config[CONF_AWAY], args, bool) | ||||
|         cg.add(action.set_away(template_)) | ||||
|     yield action | ||||
|         cg.add(var.set_away(template_)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -114,10 +114,10 @@ struct ClimateDeviceRestoreState { | ||||
|  */ | ||||
| class Climate : public Nameable { | ||||
|  public: | ||||
|   /// Construct a climate device with a name. | ||||
|   Climate(const std::string &name); | ||||
|   /// Construct a climate device with empty name (will be set later). | ||||
|   Climate(); | ||||
|   /// Construct a climate device with a name. | ||||
|   Climate(const std::string &name); | ||||
|  | ||||
|   /// The active mode of the climate device. | ||||
|   ClimateMode mode{CLIMATE_MODE_OFF}; | ||||
|   | ||||
| @@ -1,9 +1,10 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.automation import ACTION_REGISTRY, maybe_simple_id, Condition | ||||
| from esphome import automation | ||||
| from esphome.automation import maybe_simple_id, Condition | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_ID, CONF_INTERNAL, CONF_DEVICE_CLASS, CONF_STATE, \ | ||||
|     CONF_POSITION, CONF_TILT, CONF_STOP, CONF_MQTT_ID | ||||
|     CONF_POSITION, CONF_TILT, CONF_STOP, CONF_MQTT_ID, CONF_NAME | ||||
| from esphome.core import CORE, coroutine | ||||
|  | ||||
| IS_PLATFORM_COMPONENT = True | ||||
| @@ -24,7 +25,7 @@ COVER_STATES = { | ||||
|     'OPEN': COVER_OPEN, | ||||
|     'CLOSED': COVER_CLOSED, | ||||
| } | ||||
| validate_cover_state = cv.one_of(*COVER_STATES, upper=True) | ||||
| validate_cover_state = cv.enum(COVER_STATES, upper=True) | ||||
|  | ||||
| CoverOperation = cover_ns.enum('CoverOperation') | ||||
| COVER_OPERATIONS = { | ||||
| @@ -32,20 +33,20 @@ COVER_OPERATIONS = { | ||||
|     'OPENING': CoverOperation.COVER_OPERATION_OPENING, | ||||
|     'CLOSING': CoverOperation.COVER_OPERATION_CLOSING, | ||||
| } | ||||
| validate_cover_operation = cv.one_of(*COVER_OPERATIONS, upper=True) | ||||
| validate_cover_operation = cv.enum(COVER_OPERATIONS, upper=True) | ||||
|  | ||||
| # Actions | ||||
| OpenAction = cover_ns.class_('OpenAction', cg.Action) | ||||
| CloseAction = cover_ns.class_('CloseAction', cg.Action) | ||||
| StopAction = cover_ns.class_('StopAction', cg.Action) | ||||
| ControlAction = cover_ns.class_('ControlAction', cg.Action) | ||||
| CoverPublishAction = cover_ns.class_('CoverPublishAction', cg.Action) | ||||
| OpenAction = cover_ns.class_('OpenAction', automation.Action) | ||||
| CloseAction = cover_ns.class_('CloseAction', automation.Action) | ||||
| StopAction = cover_ns.class_('StopAction', automation.Action) | ||||
| ControlAction = cover_ns.class_('ControlAction', automation.Action) | ||||
| CoverPublishAction = cover_ns.class_('CoverPublishAction', automation.Action) | ||||
| CoverIsOpenCondition = cover_ns.class_('CoverIsOpenCondition', Condition) | ||||
| CoverIsClosedCondition = cover_ns.class_('CoverIsClosedCondition', Condition) | ||||
|  | ||||
| COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(Cover), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTCoverComponent), | ||||
|     cv.GenerateID(): cv.declare_id(Cover), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTCoverComponent), | ||||
|     cv.Optional(CONF_DEVICE_CLASS): cv.one_of(*DEVICE_CLASSES, lower=True), | ||||
|     # TODO: MQTT topic options | ||||
| }) | ||||
| @@ -53,6 +54,7 @@ COVER_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|  | ||||
| @coroutine | ||||
| def setup_cover_core_(var, config): | ||||
|     cg.add(var.set_name(config[CONF_NAME])) | ||||
|     if CONF_INTERNAL in config: | ||||
|         cg.add(var.set_internal(config[CONF_INTERNAL])) | ||||
|     if CONF_DEVICE_CLASS in config: | ||||
| @@ -72,63 +74,54 @@ def register_cover(var, config): | ||||
|  | ||||
|  | ||||
| COVER_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(Cover), | ||||
|     cv.Required(CONF_ID): cv.use_id(Cover), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('cover.open', COVER_ACTION_SCHEMA) | ||||
| @automation.register_action('cover.open', OpenAction, COVER_ACTION_SCHEMA) | ||||
| def cover_open_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = OpenAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('cover.close', COVER_ACTION_SCHEMA) | ||||
| @automation.register_action('cover.close', CloseAction, COVER_ACTION_SCHEMA) | ||||
| def cover_close_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = CloseAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('cover.stop', COVER_ACTION_SCHEMA) | ||||
| @automation.register_action('cover.stop', StopAction, COVER_ACTION_SCHEMA) | ||||
| def cover_stop_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = StopAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| COVER_CONTROL_ACTION_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(Cover), | ||||
|     cv.Required(CONF_ID): cv.use_id(Cover), | ||||
|     cv.Optional(CONF_STOP): cv.templatable(cv.boolean), | ||||
|     cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(cv.one_of(*COVER_STATES)), | ||||
|     cv.Exclusive(CONF_STATE, 'pos'): cv.templatable(validate_cover_state), | ||||
|     cv.Exclusive(CONF_POSITION, 'pos'): cv.templatable(cv.percentage), | ||||
|     cv.Optional(CONF_TILT): cv.templatable(cv.percentage), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('cover.control', COVER_CONTROL_ACTION_SCHEMA) | ||||
| @automation.register_action('cover.control', ControlAction, COVER_CONTROL_ACTION_SCHEMA) | ||||
| def cover_control_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = StopAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     action = cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|     if CONF_STOP in config: | ||||
|         template_ = yield cg.templatable(config[CONF_STOP], args, bool) | ||||
|         cg.add(action.set_stop(template_)) | ||||
|         cg.add(var.set_stop(template_)) | ||||
|     if CONF_STATE in config: | ||||
|         template_ = yield cg.templatable(config[CONF_STATE], args, float, | ||||
|                                          to_exp=COVER_STATES) | ||||
|         cg.add(action.set_position(template_)) | ||||
|         template_ = yield cg.templatable(config[CONF_STATE], args, float) | ||||
|         cg.add(var.set_position(template_)) | ||||
|     if CONF_POSITION in config: | ||||
|         template_ = yield cg.templatable(config[CONF_POSITION], args, float) | ||||
|         cg.add(action.set_position(template_)) | ||||
|         cg.add(var.set_position(template_)) | ||||
|     if CONF_TILT in config: | ||||
|         template_ = yield cg.templatable(config[CONF_TILT], args, float) | ||||
|         cg.add(action.set_tilt(template_)) | ||||
|     yield action | ||||
|         cg.add(var.set_tilt(template_)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -11,10 +11,7 @@ template<typename... Ts> class OpenAction : public Action<Ts...> { | ||||
|  public: | ||||
|   explicit OpenAction(Cover *cover) : cover_(cover) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->cover_->open(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->cover_->open(); } | ||||
|  | ||||
|  protected: | ||||
|   Cover *cover_; | ||||
| @@ -24,10 +21,7 @@ template<typename... Ts> class CloseAction : public Action<Ts...> { | ||||
|  public: | ||||
|   explicit CloseAction(Cover *cover) : cover_(cover) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->cover_->close(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->cover_->close(); } | ||||
|  | ||||
|  protected: | ||||
|   Cover *cover_; | ||||
| @@ -37,10 +31,7 @@ template<typename... Ts> class StopAction : public Action<Ts...> { | ||||
|  public: | ||||
|   explicit StopAction(Cover *cover) : cover_(cover) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->cover_->stop(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->cover_->stop(); } | ||||
|  | ||||
|  protected: | ||||
|   Cover *cover_; | ||||
| @@ -59,7 +50,6 @@ template<typename... Ts> class ControlAction : public Action<Ts...> { | ||||
|     if (this->tilt_.has_value()) | ||||
|       call.set_tilt(this->tilt_.value(x...)); | ||||
|     call.perform(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|  | ||||
|   TEMPLATABLE_VALUE(bool, stop) | ||||
| @@ -81,7 +71,6 @@ template<typename... Ts> class CoverPublishAction : public Action<Ts...> { | ||||
|     if (this->current_operation_.has_value()) | ||||
|       this->cover_->current_operation = this->current_operation_.value(x...); | ||||
|     this->cover_->publish_state(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|  | ||||
|   TEMPLATABLE_VALUE(float, position) | ||||
|   | ||||
| @@ -105,8 +105,8 @@ const char *cover_operation_to_str(CoverOperation op); | ||||
|  */ | ||||
| class Cover : public Nameable { | ||||
|  public: | ||||
|   explicit Cover(const std::string &name); | ||||
|   explicit Cover(); | ||||
|   explicit Cover(const std::string &name); | ||||
|  | ||||
|   /// The current operation of the cover (idle, opening, closing). | ||||
|   CoverOperation current_operation{COVER_OPERATION_IDLE}; | ||||
|   | ||||
| @@ -9,8 +9,6 @@ namespace cse7766 { | ||||
|  | ||||
| class CSE7766Component : public PollingComponent, public uart::UARTDevice { | ||||
|  public: | ||||
|   CSE7766Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
|   void set_voltage_sensor(sensor::Sensor *voltage_sensor) { voltage_sensor_ = voltage_sensor; } | ||||
|   void set_current_sensor(sensor::Sensor *current_sensor) { current_sensor_ = current_sensor; } | ||||
|   void set_power_sensor(sensor::Sensor *power_sensor) { power_sensor_ = power_sensor; } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor, uart | ||||
| from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_UPDATE_INTERVAL, CONF_VOLTAGE, \ | ||||
| from esphome.const import CONF_CURRENT, CONF_ID, CONF_POWER, CONF_VOLTAGE, \ | ||||
|     UNIT_VOLT, ICON_FLASH, UNIT_AMPERE, UNIT_WATT | ||||
|  | ||||
| DEPENDENCIES = ['uart'] | ||||
| @@ -10,18 +10,16 @@ cse7766_ns = cg.esphome_ns.namespace('cse7766') | ||||
| CSE7766Component = cse7766_ns.class_('CSE7766Component', cg.PollingComponent, uart.UARTDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CSE7766Component), | ||||
|     cv.GenerateID(): cv.declare_id(CSE7766Component), | ||||
|  | ||||
|     cv.Optional(CONF_VOLTAGE): cv.nameable(sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1)), | ||||
|     cv.Optional(CONF_CURRENT): cv.nameable( | ||||
|         sensor.sensor_schema(UNIT_AMPERE, ICON_FLASH, 2)), | ||||
|     cv.Optional(CONF_POWER): cv.nameable(sensor.sensor_schema(UNIT_WATT, ICON_FLASH, 1)), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(uart.UART_DEVICE_SCHEMA) | ||||
|     cv.Optional(CONF_VOLTAGE): sensor.sensor_schema(UNIT_VOLT, ICON_FLASH, 1), | ||||
|     cv.Optional(CONF_CURRENT): sensor.sensor_schema(UNIT_AMPERE, ICON_FLASH, 2), | ||||
|     cv.Optional(CONF_POWER): sensor.sensor_schema(UNIT_WATT, ICON_FLASH, 1), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(uart.UART_DEVICE_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield uart.register_uart_device(var, config) | ||||
|  | ||||
|   | ||||
| @@ -1,16 +1,15 @@ | ||||
| from esphome.components import binary_sensor | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA, CONF_NAME | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_BINARY_SENSORS, CONF_ID, CONF_LAMBDA | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomBinarySensorConstructor = custom_ns.class_('CustomBinarySensorConstructor') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomBinarySensorConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomBinarySensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_BINARY_SENSORS): | ||||
|         cv.ensure_list(cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA)), | ||||
|     cv.Required(CONF_BINARY_SENSORS): cv.ensure_list(binary_sensor.BINARY_SENSOR_SCHEMA), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @@ -22,5 +21,4 @@ def to_code(config): | ||||
|     custom = cg.variable(config[CONF_ID], rhs) | ||||
|     for i, conf in enumerate(config[CONF_BINARY_SENSORS]): | ||||
|         rhs = custom.Pget_binary_sensor(i) | ||||
|         cg.add(rhs.set_name(conf[CONF_NAME])) | ||||
|         yield binary_sensor.register_binary_sensor(rhs, conf) | ||||
|   | ||||
| @@ -8,22 +8,22 @@ CustomBinaryOutputConstructor = custom_ns.class_('CustomBinaryOutputConstructor' | ||||
| CustomFloatOutputConstructor = custom_ns.class_('CustomFloatOutputConstructor') | ||||
|  | ||||
| BINARY_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomBinaryOutputConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomBinaryOutputConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_TYPE): 'binary', | ||||
|     cv.Required(CONF_OUTPUTS): | ||||
|         cv.ensure_list(output.BINARY_OUTPUT_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_variable_id(output.BinaryOutput), | ||||
|             cv.GenerateID(): cv.declare_id(output.BinaryOutput), | ||||
|         })), | ||||
| }) | ||||
|  | ||||
| FLOAT_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomFloatOutputConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomFloatOutputConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_TYPE): 'float', | ||||
|     cv.Required(CONF_OUTPUTS): | ||||
|         cv.ensure_list(output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_variable_id(output.FloatOutput), | ||||
|             cv.GenerateID(): cv.declare_id(output.FloatOutput), | ||||
|         })), | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -1,17 +1,15 @@ | ||||
| from esphome.components import sensor | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_NAME, CONF_SENSORS | ||||
| from .. import custom_ns | ||||
|  | ||||
| CustomSensorConstructor = custom_ns.class_('CustomSensorConstructor') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomSensorConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomSensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA.extend({ | ||||
|         cv.GenerateID(): cv.declare_variable_id(sensor.Sensor), | ||||
|     })), | ||||
|     cv.Required(CONF_SENSORS): cv.ensure_list(sensor.SENSOR_SCHEMA), | ||||
| }) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -8,11 +8,11 @@ from .. import custom_ns | ||||
| CustomSwitchConstructor = custom_ns.class_('CustomSwitchConstructor') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomSwitchConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomSwitchConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_SWITCHES): | ||||
|         cv.ensure_list(switch.SWITCH_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_variable_id(switch.Switch), | ||||
|             cv.GenerateID(): cv.declare_id(switch.Switch), | ||||
|         })), | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -7,11 +7,11 @@ from .. import custom_ns | ||||
| CustomTextSensorConstructor = custom_ns.class_('CustomTextSensorConstructor') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomTextSensorConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomTextSensorConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Required(CONF_TEXT_SENSORS): | ||||
|         cv.ensure_list(text_sensor.TEXT_SENSOR_SCHEMA.extend({ | ||||
|             cv.GenerateID(): cv.declare_variable_id(text_sensor.TextSensor), | ||||
|             cv.GenerateID(): cv.declare_id(text_sensor.TextSensor), | ||||
|         })), | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -7,10 +7,10 @@ CustomComponentConstructor = custom_component_ns.class_('CustomComponentConstruc | ||||
|  | ||||
| MULTI_CONF = True | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(CustomComponentConstructor), | ||||
|     cv.GenerateID(): cv.declare_id(CustomComponentConstructor), | ||||
|     cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     cv.Optional(CONF_COMPONENTS): cv.ensure_list(cv.Schema({ | ||||
|         cv.GenerateID(): cv.declare_variable_id(cg.Component) | ||||
|         cv.GenerateID(): cv.declare_id(cg.Component) | ||||
|     }).extend(cv.COMPONENT_SCHEMA)), | ||||
| }) | ||||
|  | ||||
|   | ||||
| @@ -9,12 +9,10 @@ namespace cwww { | ||||
|  | ||||
| class CWWWLightOutput : public light::LightOutput { | ||||
|  public: | ||||
|   CWWWLightOutput(output::FloatOutput *cold_white, output::FloatOutput *warm_white, float cold_white_temperature, | ||||
|                   float warm_white_temperature) | ||||
|       : cold_white_(cold_white), | ||||
|         warm_white_(warm_white), | ||||
|         cold_white_temperature_(cold_white_temperature), | ||||
|         warm_white_temperature_(warm_white_temperature) {} | ||||
|   void set_cold_white(output::FloatOutput *cold_white) { cold_white_ = cold_white; } | ||||
|   void set_warm_white(output::FloatOutput *warm_white) { warm_white_ = warm_white; } | ||||
|   void set_cold_white_temperature(float cold_white_temperature) { cold_white_temperature_ = cold_white_temperature; } | ||||
|   void set_warm_white_temperature(float warm_white_temperature) { warm_white_temperature_ = warm_white_temperature; } | ||||
|   light::LightTraits get_traits() override { | ||||
|     auto traits = light::LightTraits(); | ||||
|     traits.set_supports_brightness(true); | ||||
|   | ||||
| @@ -7,19 +7,22 @@ from esphome.const import CONF_OUTPUT_ID, CONF_COLD_WHITE, CONF_WARM_WHITE, \ | ||||
| cwww_ns = cg.esphome_ns.namespace('cwww') | ||||
| CWWWLightOutput = cwww_ns.class_('CWWWLightOutput', light.LightOutput) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(light.RGB_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(CWWWLightOutput), | ||||
|     cv.Required(CONF_COLD_WHITE): cv.use_variable_id(output.FloatOutput), | ||||
|     cv.Required(CONF_WARM_WHITE): cv.use_variable_id(output.FloatOutput), | ||||
| CONFIG_SCHEMA = light.RGB_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(CWWWLightOutput), | ||||
|     cv.Required(CONF_COLD_WHITE): cv.use_id(output.FloatOutput), | ||||
|     cv.Required(CONF_WARM_WHITE): cv.use_id(output.FloatOutput), | ||||
|     cv.Required(CONF_COLD_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
|     cv.Required(CONF_WARM_WHITE_COLOR_TEMPERATURE): cv.color_temperature, | ||||
| })) | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     cwhite = yield cg.get_variable(config[CONF_COLD_WHITE]) | ||||
|     wwhite = yield cg.get_variable(config[CONF_WARM_WHITE]) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID], cwhite, wwhite, | ||||
|                            config[CONF_COLD_WHITE_COLOR_TEMPERATURE], | ||||
|                            config[CONF_WARM_WHITE_COLOR_TEMPERATURE]) | ||||
|     var = cg.new_Pvariable(config[CONF_OUTPUT_ID]) | ||||
|     yield light.register_light(var, config) | ||||
|     cwhite = yield cg.get_variable(config[CONF_COLD_WHITE]) | ||||
|     cg.add(var.set_cold_white(cwhite)) | ||||
|     cg.add(var.set_cold_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])) | ||||
|  | ||||
|     wwhite = yield cg.get_variable(config[CONF_WARM_WHITE]) | ||||
|     cg.add(var.set_warm_white(wwhite)) | ||||
|     cg.add(var.set_warm_white_temperature(config[CONF_COLD_WHITE_COLOR_TEMPERATURE])) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_ID, CONF_PIN, CONF_UPDATE_INTERVAL | ||||
| from esphome.const import CONF_ID, CONF_PIN | ||||
|  | ||||
| MULTI_CONF = True | ||||
| AUTO_LOAD = ['sensor'] | ||||
| @@ -12,15 +12,14 @@ DallasComponent = dallas_ns.class_('DallasComponent', cg.PollingComponent) | ||||
| ESPOneWire = dallas_ns.class_('ESPOneWire') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DallasComponent), | ||||
|     cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_variable_id(ESPOneWire), | ||||
|     cv.GenerateID(): cv.declare_id(DallasComponent), | ||||
|     cv.GenerateID(CONF_ONE_WIRE_ID): cv.declare_id(ESPOneWire), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     one_wire = cg.new_Pvariable(config[CONF_ONE_WIRE_ID], pin) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], one_wire, config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], one_wire) | ||||
|     yield cg.register_component(var, config) | ||||
|   | ||||
| @@ -95,15 +95,13 @@ void DallasComponent::dump_config() { | ||||
|   } | ||||
| } | ||||
|  | ||||
| DallasTemperatureSensor *DallasComponent::get_sensor_by_address(const std::string &name, uint64_t address, | ||||
|                                                                 uint8_t resolution) { | ||||
|   auto s = new DallasTemperatureSensor(name, address, resolution, this); | ||||
| DallasTemperatureSensor *DallasComponent::get_sensor_by_address(uint64_t address, uint8_t resolution) { | ||||
|   auto s = new DallasTemperatureSensor(address, resolution, this); | ||||
|   this->sensors_.push_back(s); | ||||
|   return s; | ||||
| } | ||||
| DallasTemperatureSensor *DallasComponent::get_sensor_by_index(const std::string &name, uint8_t index, | ||||
|                                                               uint8_t resolution) { | ||||
|   auto s = this->get_sensor_by_address(name, 0, resolution); | ||||
| DallasTemperatureSensor *DallasComponent::get_sensor_by_index(uint8_t index, uint8_t resolution) { | ||||
|   auto s = this->get_sensor_by_address(0, resolution); | ||||
|   s->set_index(index); | ||||
|   return s; | ||||
| } | ||||
| @@ -148,12 +146,10 @@ void DallasComponent::update() { | ||||
|     }); | ||||
|   } | ||||
| } | ||||
| DallasComponent::DallasComponent(ESPOneWire *one_wire, uint32_t update_interval) | ||||
|     : PollingComponent(update_interval), one_wire_(one_wire) {} | ||||
| DallasComponent::DallasComponent(ESPOneWire *one_wire) : one_wire_(one_wire) {} | ||||
|  | ||||
| DallasTemperatureSensor::DallasTemperatureSensor(const std::string &name, uint64_t address, uint8_t resolution, | ||||
|                                                  DallasComponent *parent) | ||||
|     : sensor::Sensor(name), parent_(parent) { | ||||
| DallasTemperatureSensor::DallasTemperatureSensor(uint64_t address, uint8_t resolution, DallasComponent *parent) | ||||
|     : parent_(parent) { | ||||
|   this->set_address(address); | ||||
|   this->set_resolution(resolution); | ||||
| } | ||||
|   | ||||
| @@ -11,10 +11,10 @@ class DallasTemperatureSensor; | ||||
|  | ||||
| class DallasComponent : public PollingComponent { | ||||
|  public: | ||||
|   explicit DallasComponent(ESPOneWire *one_wire, uint32_t update_interval); | ||||
|   explicit DallasComponent(ESPOneWire *one_wire); | ||||
|  | ||||
|   DallasTemperatureSensor *get_sensor_by_address(const std::string &name, uint64_t address, uint8_t resolution); | ||||
|   DallasTemperatureSensor *get_sensor_by_index(const std::string &name, uint8_t index, uint8_t resolution); | ||||
|   DallasTemperatureSensor *get_sensor_by_address(uint64_t address, uint8_t resolution); | ||||
|   DallasTemperatureSensor *get_sensor_by_index(uint8_t index, uint8_t resolution); | ||||
|  | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
| @@ -33,7 +33,7 @@ class DallasComponent : public PollingComponent { | ||||
| /// Internal class that helps us create multiple sensors for one Dallas hub. | ||||
| class DallasTemperatureSensor : public sensor::Sensor { | ||||
|  public: | ||||
|   DallasTemperatureSensor(const std::string &name, uint64_t address, uint8_t resolution, DallasComponent *parent); | ||||
|   DallasTemperatureSensor(uint64_t address, uint8_t resolution, DallasComponent *parent); | ||||
|  | ||||
|   /// Helper to get a pointer to the address as uint8_t. | ||||
|   uint8_t *get_address8(); | ||||
|   | ||||
| @@ -1,24 +1,19 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_NAME, \ | ||||
|     CONF_RESOLUTION, CONF_UNIT_OF_MEASUREMENT, UNIT_CELSIUS, CONF_ICON, ICON_THERMOMETER, \ | ||||
|     CONF_ACCURACY_DECIMALS, CONF_ID | ||||
| from esphome.const import CONF_ADDRESS, CONF_DALLAS_ID, CONF_INDEX, CONF_RESOLUTION, UNIT_CELSIUS, \ | ||||
|     ICON_THERMOMETER, CONF_ID | ||||
| from . import DallasComponent, dallas_ns | ||||
|  | ||||
| DallasTemperatureSensor = dallas_ns.class_('DallasTemperatureSensor', sensor.Sensor) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DallasTemperatureSensor), | ||||
|     cv.GenerateID(CONF_DALLAS_ID): cv.use_variable_id(DallasComponent), | ||||
| CONFIG_SCHEMA = cv.All(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DallasTemperatureSensor), | ||||
|     cv.GenerateID(CONF_DALLAS_ID): cv.use_id(DallasComponent), | ||||
|  | ||||
|     cv.Optional(CONF_ADDRESS): cv.hex_int, | ||||
|     cv.Optional(CONF_INDEX): cv.positive_int, | ||||
|     cv.Optional(CONF_RESOLUTION, default=12): cv.All(cv.int_, cv.Range(min=9, max=12)), | ||||
|  | ||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_CELSIUS): sensor.unit_of_measurement, | ||||
|     cv.Optional(CONF_ICON, default=ICON_THERMOMETER): sensor.icon, | ||||
|     cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals, | ||||
| }), cv.has_exactly_one_key(CONF_ADDRESS, CONF_INDEX)) | ||||
|  | ||||
|  | ||||
| @@ -26,9 +21,8 @@ def to_code(config): | ||||
|     hub = yield cg.get_variable(config[CONF_DALLAS_ID]) | ||||
|     if CONF_ADDRESS in config: | ||||
|         address = config[CONF_ADDRESS] | ||||
|         rhs = hub.Pget_sensor_by_address(config[CONF_NAME], address, config.get(CONF_RESOLUTION)) | ||||
|         rhs = hub.Pget_sensor_by_address(address, config.get(CONF_RESOLUTION)) | ||||
|     else: | ||||
|         rhs = hub.Pget_sensor_by_index(config[CONF_NAME], config[CONF_INDEX], | ||||
|                                        config.get(CONF_RESOLUTION)) | ||||
|         rhs = hub.Pget_sensor_by_index(config[CONF_INDEX], config.get(CONF_RESOLUTION)) | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|   | ||||
| @@ -7,11 +7,10 @@ DEPENDENCIES = ['logger'] | ||||
| debug_ns = cg.esphome_ns.namespace('debug') | ||||
| DebugComponent = debug_ns.class_('DebugComponent', cg.Component) | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DebugComponent), | ||||
|     cv.GenerateID(): cv.declare_id(DebugComponent), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     rhs = DebugComponent.new() | ||||
|     var = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| from esphome import pins | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.automation import ACTION_REGISTRY, maybe_simple_id | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins, automation | ||||
| from esphome.automation import maybe_simple_id | ||||
| from esphome.const import CONF_ID, CONF_MODE, CONF_NUMBER, CONF_PINS, CONF_RUN_CYCLES, \ | ||||
|     CONF_RUN_DURATION, CONF_SLEEP_DURATION, CONF_WAKEUP_PIN | ||||
|  | ||||
| @@ -16,8 +16,8 @@ def validate_pin_number(value): | ||||
|  | ||||
| deep_sleep_ns = cg.esphome_ns.namespace('deep_sleep') | ||||
| DeepSleepComponent = deep_sleep_ns.class_('DeepSleepComponent', cg.Component) | ||||
| EnterDeepSleepAction = deep_sleep_ns.class_('EnterDeepSleepAction', cg.Action) | ||||
| PreventDeepSleepAction = deep_sleep_ns.class_('PreventDeepSleepAction', cg.Action) | ||||
| EnterDeepSleepAction = deep_sleep_ns.class_('EnterDeepSleepAction', automation.Action) | ||||
| PreventDeepSleepAction = deep_sleep_ns.class_('PreventDeepSleepAction', automation.Action) | ||||
|  | ||||
| WakeupPinMode = deep_sleep_ns.enum('WakeupPinMode') | ||||
| WAKEUP_PIN_MODES = { | ||||
| @@ -37,17 +37,17 @@ CONF_WAKEUP_PIN_MODE = 'wakeup_pin_mode' | ||||
| CONF_ESP32_EXT1_WAKEUP = 'esp32_ext1_wakeup' | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DeepSleepComponent), | ||||
|     cv.GenerateID(): cv.declare_id(DeepSleepComponent), | ||||
|     cv.Optional(CONF_RUN_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Optional(CONF_SLEEP_DURATION): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_WAKEUP_PIN): cv.All(cv.only_on_esp32, pins.internal_gpio_input_pin_schema, | ||||
|                                          validate_pin_number), | ||||
|     cv.Optional(CONF_WAKEUP_PIN_MODE): cv.All(cv.only_on_esp32, | ||||
|                                               cv.one_of(*WAKEUP_PIN_MODES), upper=True), | ||||
|                                               cv.enum(WAKEUP_PIN_MODES), upper=True), | ||||
|     cv.Optional(CONF_ESP32_EXT1_WAKEUP): cv.All(cv.only_on_esp32, cv.Schema({ | ||||
|         cv.Required(CONF_PINS): cv.ensure_list(pins.shorthand_input_pin, validate_pin_number), | ||||
|         cv.Required(CONF_MODE): cv.one_of(*EXT1_WAKEUP_MODES, upper=True), | ||||
|         cv.Required(CONF_MODE): cv.enum(EXT1_WAKEUP_MODES, upper=True), | ||||
|     })), | ||||
|  | ||||
|     cv.Optional(CONF_RUN_CYCLES): cv.invalid("The run_cycles option has been removed in 1.11.0 as " | ||||
| @@ -66,7 +66,7 @@ def to_code(config): | ||||
|         pin = yield cg.gpio_pin_expression(config[CONF_WAKEUP_PIN]) | ||||
|         cg.add(var.set_wakeup_pin(pin)) | ||||
|     if CONF_WAKEUP_PIN_MODE in config: | ||||
|         cg.add(var.set_wakeup_pin_mode(WAKEUP_PIN_MODES[config[CONF_WAKEUP_PIN_MODE]])) | ||||
|         cg.add(var.set_wakeup_pin_mode(config[CONF_WAKEUP_PIN_MODE])) | ||||
|     if CONF_RUN_DURATION in config: | ||||
|         cg.add(var.set_run_duration(config[CONF_RUN_DURATION])) | ||||
|  | ||||
| @@ -78,7 +78,7 @@ def to_code(config): | ||||
|         struct = cg.StructInitializer( | ||||
|             Ext1Wakeup, | ||||
|             ('mask', mask), | ||||
|             ('wakeup_mode', EXT1_WAKEUP_MODES[conf[CONF_MODE]]) | ||||
|             ('wakeup_mode', conf[CONF_MODE]) | ||||
|         ) | ||||
|         cg.add(var.set_ext1_wakeup(struct)) | ||||
|  | ||||
| @@ -86,21 +86,17 @@ def to_code(config): | ||||
|  | ||||
|  | ||||
| DEEP_SLEEP_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(DeepSleepComponent), | ||||
|     cv.GenerateID(): cv.use_id(DeepSleepComponent), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('deep_sleep.enter', DEEP_SLEEP_ACTION_SCHEMA) | ||||
| @automation.register_action('deep_sleep.enter', EnterDeepSleepAction, DEEP_SLEEP_ACTION_SCHEMA) | ||||
| def deep_sleep_enter_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = EnterDeepSleepAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('deep_sleep.prevent', DEEP_SLEEP_ACTION_SCHEMA) | ||||
| @automation.register_action('deep_sleep.prevent', PreventDeepSleepAction, DEEP_SLEEP_ACTION_SCHEMA) | ||||
| def deep_sleep_prevent_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = PreventDeepSleepAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|   | ||||
| @@ -85,10 +85,7 @@ template<typename... Ts> class EnterDeepSleepAction : public Action<Ts...> { | ||||
|  public: | ||||
|   EnterDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->deep_sleep_->begin_sleep(true); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->deep_sleep_->begin_sleep(true); } | ||||
|  | ||||
|  protected: | ||||
|   DeepSleepComponent *deep_sleep_; | ||||
| @@ -98,10 +95,7 @@ template<typename... Ts> class PreventDeepSleepAction : public Action<Ts...> { | ||||
|  public: | ||||
|   PreventDeepSleepAction(DeepSleepComponent *deep_sleep) : deep_sleep_(deep_sleep) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->deep_sleep_->prevent_deep_sleep(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->deep_sleep_->prevent_deep_sleep(); } | ||||
|  | ||||
|  protected: | ||||
|   DeepSleepComponent *deep_sleep_; | ||||
|   | ||||
| @@ -7,12 +7,6 @@ namespace dht { | ||||
|  | ||||
| static const char *TAG = "dht"; | ||||
|  | ||||
| DHT::DHT(const std::string &temperature_name, const std::string &humidity_name, GPIOPin *pin, uint32_t update_interval) | ||||
|     : PollingComponent(update_interval), | ||||
|       pin_(pin), | ||||
|       temperature_sensor_(new sensor::Sensor(temperature_name)), | ||||
|       humidity_sensor_(new sensor::Sensor(humidity_name)) {} | ||||
|  | ||||
| void DHT::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up DHT..."); | ||||
|   this->pin_->digital_write(true); | ||||
| @@ -71,8 +65,6 @@ void DHT::set_dht_model(DHTModel model) { | ||||
|   this->model_ = model; | ||||
|   this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT; | ||||
| } | ||||
| sensor::Sensor *DHT::get_temperature_sensor() const { return this->temperature_sensor_; } | ||||
| sensor::Sensor *DHT::get_humidity_sensor() const { return this->humidity_sensor_; } | ||||
| bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_errors) { | ||||
|   *humidity = NAN; | ||||
|   *temperature = NAN; | ||||
|   | ||||
| @@ -18,13 +18,6 @@ enum DHTModel { | ||||
| /// Component for reading temperature/humidity measurements from DHT11/DHT22 sensors. | ||||
| class DHT : public PollingComponent { | ||||
|  public: | ||||
|   /** Construct a DHTComponent. | ||||
|    * | ||||
|    * @param pin The pin which DHT sensor is connected to. | ||||
|    * @param update_interval The interval in ms the sensor should be checked. | ||||
|    */ | ||||
|   DHT(const std::string &temperature_name, const std::string &humidity_name, GPIOPin *pin, uint32_t update_interval); | ||||
|  | ||||
|   /** Manually select the DHT model. | ||||
|    * | ||||
|    * Valid values are: | ||||
| @@ -40,10 +33,10 @@ class DHT : public PollingComponent { | ||||
|    */ | ||||
|   void set_dht_model(DHTModel model); | ||||
|  | ||||
|   // ========== INTERNAL METHODS ========== | ||||
|   // (In most use cases you won't need these) | ||||
|   sensor::Sensor *get_temperature_sensor() const; | ||||
|   sensor::Sensor *get_humidity_sensor() const; | ||||
|   void set_pin(GPIOPin *pin) { pin_ = pin; } | ||||
|   void set_model(DHTModel model) { model_ = model; } | ||||
|   void set_temperature_sensor(sensor::Sensor *temperature_sensor) { temperature_sensor_ = temperature_sensor; } | ||||
|   void set_humidity_sensor(sensor::Sensor *humidity_sensor) { humidity_sensor_ = humidity_sensor; } | ||||
|  | ||||
|   /// Set up the pins and check connection. | ||||
|   void setup() override; | ||||
| @@ -59,8 +52,8 @@ class DHT : public PollingComponent { | ||||
|   GPIOPin *pin_; | ||||
|   DHTModel model_{DHT_MODEL_AUTO_DETECT}; | ||||
|   bool is_auto_detect_{false}; | ||||
|   sensor::Sensor *temperature_sensor_; | ||||
|   sensor::Sensor *humidity_sensor_; | ||||
|   sensor::Sensor *temperature_sensor_{nullptr}; | ||||
|   sensor::Sensor *humidity_sensor_{nullptr}; | ||||
| }; | ||||
|  | ||||
| }  // namespace dht | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| from esphome.components import sensor | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_NAME, \ | ||||
|     CONF_PIN, CONF_TEMPERATURE, CONF_UPDATE_INTERVAL, CONF_ACCURACY_DECIMALS, CONF_ICON, \ | ||||
|     ICON_THERMOMETER, CONF_UNIT_OF_MEASUREMENT, UNIT_CELSIUS, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_MODEL, CONF_PIN, CONF_TEMPERATURE, \ | ||||
|     CONF_UPDATE_INTERVAL, ICON_THERMOMETER, UNIT_CELSIUS, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
| from esphome.cpp_helpers import gpio_pin_expression | ||||
| from esphome.pins import gpio_input_pullup_pin_schema | ||||
|  | ||||
| dht_ns = cg.esphome_ns.namespace('dht') | ||||
| DHTModel = dht_ns.enum('DHTModel') | ||||
| @@ -20,31 +19,27 @@ DHT_MODELS = { | ||||
| DHT = dht_ns.class_('DHT', cg.PollingComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DHT), | ||||
|     cv.Required(CONF_PIN): gpio_input_pullup_pin_schema, | ||||
|     cv.Required(CONF_TEMPERATURE): cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|         cv.Optional(CONF_ACCURACY_DECIMALS, default=1): sensor.accuracy_decimals, | ||||
|         cv.Optional(CONF_ICON, default=ICON_THERMOMETER): sensor.icon, | ||||
|         cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_CELSIUS): sensor.unit_of_measurement, | ||||
|     })), | ||||
|     cv.Required(CONF_HUMIDITY): cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|         cv.Optional(CONF_ACCURACY_DECIMALS, default=0): sensor.accuracy_decimals, | ||||
|         cv.Optional(CONF_ICON, default=ICON_WATER_PERCENT): sensor.icon, | ||||
|         cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_PERCENT): sensor.unit_of_measurement, | ||||
|     })), | ||||
|     cv.Optional(CONF_MODEL, default='auto detect'): cv.one_of(*DHT_MODELS, upper=True, space='_'), | ||||
|     cv.GenerateID(): cv.declare_id(DHT), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema, | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 0), | ||||
|     cv.Optional(CONF_MODEL, default='auto detect'): cv.enum(DHT_MODELS, upper=True, space='_'), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = yield gpio_pin_expression(config[CONF_PIN]) | ||||
|     rhs = DHT.new(config[CONF_TEMPERATURE][CONF_NAME], | ||||
|                   config[CONF_HUMIDITY][CONF_NAME], | ||||
|                   pin, config[CONF_UPDATE_INTERVAL]) | ||||
|     dht = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(dht, config) | ||||
|     yield sensor.register_sensor(dht.Pget_temperature_sensor(), config[CONF_TEMPERATURE]) | ||||
|     yield sensor.register_sensor(dht.Pget_humidity_sensor(), config[CONF_HUMIDITY]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|  | ||||
|     cg.add(dht.set_dht_model(DHT_MODELS[config[CONF_MODEL]])) | ||||
|     pin = yield gpio_pin_expression(config[CONF_PIN]) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|  | ||||
|     if CONF_TEMPERATURE in config: | ||||
|         sens = yield sensor.new_sensor(config[CONF_TEMPERATURE]) | ||||
|         cg.add(var.set_temperature_sensor(sens)) | ||||
|     if CONF_HUMIDITY in config: | ||||
|         sens = yield sensor.new_sensor(config[CONF_HUMIDITY]) | ||||
|         cg.add(var.set_humidity_sensor(sens)) | ||||
|  | ||||
|     cg.add(var.set_dht_model(config[CONF_MODEL])) | ||||
|   | ||||
| @@ -9,8 +9,6 @@ namespace dht12 { | ||||
|  | ||||
| class DHT12Component : public PollingComponent, public i2c::I2CDevice { | ||||
|  public: | ||||
|   DHT12Component(uint32_t update_interval) : PollingComponent(update_interval) {} | ||||
|  | ||||
|   void setup() override; | ||||
|   void dump_config() override; | ||||
|   float get_setup_priority() const override; | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import i2c, sensor | ||||
| from esphome.const import CONF_HUMIDITY, CONF_ID, CONF_TEMPERATURE, \ | ||||
|     CONF_UPDATE_INTERVAL, UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
|     UNIT_CELSIUS, ICON_THERMOMETER, ICON_WATER_PERCENT, UNIT_PERCENT | ||||
|  | ||||
| DEPENDENCIES = ['i2c'] | ||||
|  | ||||
| @@ -10,17 +10,14 @@ dht12_ns = cg.esphome_ns.namespace('dht12') | ||||
| DHT12Component = dht12_ns.class_('DHT12Component', cg.PollingComponent, i2c.I2CDevice) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DHT12Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): | ||||
|         cv.nameable(sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1)), | ||||
|     cv.Optional(CONF_HUMIDITY): | ||||
|         cv.nameable(sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1)), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA).extend(i2c.i2c_device_schema(0x5C)) | ||||
|     cv.GenerateID(): cv.declare_id(DHT12Component), | ||||
|     cv.Optional(CONF_TEMPERATURE): sensor.sensor_schema(UNIT_CELSIUS, ICON_THERMOMETER, 1), | ||||
|     cv.Optional(CONF_HUMIDITY): sensor.sensor_schema(UNIT_PERCENT, ICON_WATER_PERCENT, 1), | ||||
| }).extend(cv.polling_component_schema('60s')).extend(i2c.i2c_device_schema(0x5C)) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_UPDATE_INTERVAL]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield i2c.register_i2c_device(var, config) | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| # coding=utf-8 | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import core | ||||
| from esphome.automation import ACTION_REGISTRY, maybe_simple_id | ||||
| from esphome import core, automation | ||||
| from esphome.automation import maybe_simple_id | ||||
| from esphome.const import CONF_ID, CONF_LAMBDA, CONF_PAGES, CONF_ROTATION, CONF_UPDATE_INTERVAL | ||||
| from esphome.core import coroutine | ||||
|  | ||||
| @@ -13,9 +13,9 @@ DisplayBuffer = display_ns.class_('DisplayBuffer') | ||||
| DisplayPage = display_ns.class_('DisplayPage') | ||||
| DisplayPagePtr = DisplayPage.operator('ptr') | ||||
| DisplayBufferRef = DisplayBuffer.operator('ref') | ||||
| DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', cg.Action) | ||||
| DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', cg.Action) | ||||
| DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', cg.Action) | ||||
| DisplayPageShowAction = display_ns.class_('DisplayPageShowAction', automation.Action) | ||||
| DisplayPageShowNextAction = display_ns.class_('DisplayPageShowNextAction', automation.Action) | ||||
| DisplayPageShowPrevAction = display_ns.class_('DisplayPageShowPrevAction', automation.Action) | ||||
|  | ||||
| DISPLAY_ROTATIONS = { | ||||
|     0: display_ns.DISPLAY_ROTATION_0_DEGREES, | ||||
| @@ -29,11 +29,7 @@ def validate_rotation(value): | ||||
|     value = cv.string(value) | ||||
|     if value.endswith(u"°"): | ||||
|         value = value[:-1] | ||||
|     try: | ||||
|         value = int(value) | ||||
|     except ValueError: | ||||
|         raise cv.Invalid(u"Expected integer for rotation") | ||||
|     return cv.one_of(*DISPLAY_ROTATIONS)(value) | ||||
|     return cv.enum(DISPLAY_ROTATIONS, int=True)(value) | ||||
|  | ||||
|  | ||||
| BASIC_DISPLAY_SCHEMA = cv.Schema({ | ||||
| @@ -44,7 +40,7 @@ BASIC_DISPLAY_SCHEMA = cv.Schema({ | ||||
| FULL_DISPLAY_SCHEMA = BASIC_DISPLAY_SCHEMA.extend({ | ||||
|     cv.Optional(CONF_ROTATION): validate_rotation, | ||||
|     cv.Optional(CONF_PAGES): cv.All(cv.ensure_list({ | ||||
|         cv.GenerateID(): cv.declare_variable_id(DisplayPage), | ||||
|         cv.GenerateID(): cv.declare_id(DisplayPage), | ||||
|         cv.Required(CONF_LAMBDA): cv.lambda_, | ||||
|     }), cv.Length(min=1)), | ||||
| }) | ||||
| @@ -71,37 +67,35 @@ def register_display(var, config): | ||||
|     yield setup_display_core_(var, config) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('display.page.show', maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayPage)), | ||||
| @automation.register_action('display.page.show', DisplayPageShowAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayPage)), | ||||
| })) | ||||
| def display_page_show_to_code(config, action_id, template_arg, args): | ||||
|     type = DisplayPageShowAction.template(template_arg) | ||||
|     action = cg.Pvariable(action_id, type.new(), type=type) | ||||
|     var = cg.new_Pvariable(action_id, template_arg) | ||||
|     if isinstance(config[CONF_ID], core.Lambda): | ||||
|         template_ = yield cg.templatable(config[CONF_ID], args, DisplayPagePtr) | ||||
|         cg.add(action.set_page(template_)) | ||||
|         cg.add(var.set_page(template_)) | ||||
|     else: | ||||
|         var = yield cg.get_variable(config[CONF_ID]) | ||||
|         cg.add(action.set_page(var)) | ||||
|     yield action | ||||
|         paren = yield cg.get_variable(config[CONF_ID]) | ||||
|         cg.add(var.set_page(paren)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('display.page.show_next', maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), | ||||
| @automation.register_action('display.page.show_next', DisplayPageShowNextAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
| })) | ||||
| def display_page_show_next_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = DisplayPageShowNextAction.template(template_arg) | ||||
|     yield cg.Pvariable(action_id, type.new(var), type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('display.page.show_previous', maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.templatable(cv.use_variable_id(DisplayBuffer)), | ||||
| })) | ||||
| @automation.register_action('display.page.show_previous', DisplayPageShowPrevAction, | ||||
|                             maybe_simple_id({ | ||||
|                                 cv.Required(CONF_ID): cv.templatable(cv.use_id(DisplayBuffer)), | ||||
|                             })) | ||||
| def display_page_show_previous_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = DisplayPageShowPrevAction.template(template_arg) | ||||
|     yield cg.Pvariable(action_id, type.new(var), type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -396,17 +396,13 @@ template<typename... Ts> class DisplayPageShowAction : public Action<Ts...> { | ||||
|     if (page != nullptr) { | ||||
|       page->show(); | ||||
|     } | ||||
|     this->play_next(x...); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> { | ||||
|  public: | ||||
|   DisplayPageShowNextAction(DisplayBuffer *buffer) : buffer_(buffer) {} | ||||
|   void play(Ts... x) override { | ||||
|     this->buffer_->show_next_page(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->buffer_->show_next_page(); } | ||||
|  | ||||
|  protected: | ||||
|   DisplayBuffer *buffer_; | ||||
| @@ -415,10 +411,7 @@ template<typename... Ts> class DisplayPageShowNextAction : public Action<Ts...> | ||||
| template<typename... Ts> class DisplayPageShowPrevAction : public Action<Ts...> { | ||||
|  public: | ||||
|   DisplayPageShowPrevAction(DisplayBuffer *buffer) : buffer_(buffer) {} | ||||
|   void play(Ts... x) override { | ||||
|     this->buffer_->show_prev_page(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->buffer_->show_prev_page(); } | ||||
|  | ||||
|  protected: | ||||
|   DisplayBuffer *buffer_; | ||||
|   | ||||
| @@ -17,10 +17,9 @@ struct DutyCycleSensorStore { | ||||
|   static void gpio_intr(DutyCycleSensorStore *arg); | ||||
| }; | ||||
|  | ||||
| class DutyCycleSensor : public sensor::PollingSensorComponent { | ||||
| class DutyCycleSensor : public sensor::Sensor, public PollingComponent { | ||||
|  public: | ||||
|   DutyCycleSensor(const std::string &name, uint32_t update_interval, GPIOPin *pin) | ||||
|       : PollingSensorComponent(name, update_interval), pin_(pin) {} | ||||
|   void set_pin(GPIOPin *pin) { pin_ = pin; } | ||||
|  | ||||
|   void setup() override; | ||||
|   float get_setup_priority() const override; | ||||
|   | ||||
| @@ -1,23 +1,23 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_ID, CONF_NAME, CONF_PIN, CONF_UPDATE_INTERVAL, UNIT_PERCENT, \ | ||||
|     ICON_PERCENT | ||||
| from esphome.const import CONF_ID, CONF_PIN, UNIT_PERCENT, ICON_PERCENT | ||||
|  | ||||
| duty_cycle_ns = cg.esphome_ns.namespace('duty_cycle') | ||||
| DutyCycleSensor = duty_cycle_ns.class_('DutyCycleSensor', sensor.PollingSensorComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(DutyCycleSensor), | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_PERCENT, ICON_PERCENT, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(DutyCycleSensor), | ||||
|     cv.Required(CONF_PIN): cv.All(pins.internal_gpio_input_pin_schema, | ||||
|                                   pins.validate_has_interrupt), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(cv.polling_component_schema('60s')) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME], config[CONF_UPDATE_INTERVAL], pin) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield sensor.register_sensor(var, config) | ||||
|  | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|   | ||||
| @@ -1,32 +1,32 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.components import binary_sensor, cover | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, \ | ||||
|     CONF_CLOSE_ENDSTOP, CONF_ID, CONF_NAME, CONF_OPEN_ACTION, CONF_OPEN_DURATION, \ | ||||
|     CONF_CLOSE_ENDSTOP, CONF_ID, CONF_OPEN_ACTION, CONF_OPEN_DURATION, \ | ||||
|     CONF_OPEN_ENDSTOP, CONF_STOP_ACTION, CONF_MAX_DURATION | ||||
|  | ||||
| endstop_ns = cg.esphome_ns.namespace('endstop') | ||||
| EndstopCover = endstop_ns.class_('EndstopCover', cover.Cover, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(cover.COVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(EndstopCover), | ||||
| CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(EndstopCover), | ||||
|     cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True), | ||||
|  | ||||
|     cv.Required(CONF_OPEN_ENDSTOP): cv.use_variable_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_OPEN_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_OPEN_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Required(CONF_OPEN_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True), | ||||
|     cv.Required(CONF_CLOSE_ENDSTOP): cv.use_variable_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_CLOSE_ENDSTOP): cv.use_id(binary_sensor.BinarySensor), | ||||
|     cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds, | ||||
|  | ||||
|     cv.Optional(CONF_MAX_DURATION): cv.positive_time_period_milliseconds, | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield cover.register_cover(var, config) | ||||
|  | ||||
|   | ||||
| @@ -10,8 +10,6 @@ namespace endstop { | ||||
|  | ||||
| class EndstopCover : public cover::Cover, public Component { | ||||
|  public: | ||||
|   EndstopCover(const std::string &name) : cover::Cover(name) {} | ||||
|  | ||||
|   void setup() override; | ||||
|   void loop() override; | ||||
|   void dump_config() override; | ||||
|   | ||||
| @@ -12,7 +12,7 @@ CONF_MAJOR = 'major' | ||||
| CONF_MINOR = 'minor' | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32BLEBeacon), | ||||
|     cv.GenerateID(): cv.declare_id(ESP32BLEBeacon), | ||||
|     cv.Required(CONF_TYPE): cv.one_of('IBEACON', upper=True), | ||||
|     cv.Required(CONF_UUID): cv.uuid, | ||||
|     cv.Optional(CONF_MAJOR, default=10167): cv.uint16_t, | ||||
|   | ||||
| @@ -11,12 +11,12 @@ ESP32BLETracker = esp32_ble_tracker_ns.class_('ESP32BLETracker', cg.Component) | ||||
| ESPBTDeviceListener = esp32_ble_tracker_ns.class_('ESPBTDeviceListener') | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32BLETracker), | ||||
|     cv.GenerateID(): cv.declare_id(ESP32BLETracker), | ||||
|     cv.Optional(CONF_SCAN_INTERVAL, default='300s'): cv.positive_time_period_seconds, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| ESP_BLE_DEVICE_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_variable_id(ESP32BLETracker), | ||||
|     cv.GenerateID(CONF_ESP32_BLE_ID): cv.use_id(ESP32BLETracker), | ||||
| }) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -58,7 +58,7 @@ CONF_TEST_PATTERN = 'test_pattern' | ||||
| camera_range_param = cv.All(cv.int_, cv.Range(min=-2, max=2)) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32Camera), | ||||
|     cv.GenerateID(): cv.declare_id(ESP32Camera), | ||||
|     cv.Required(CONF_NAME): cv.string, | ||||
|     cv.Required(CONF_DATA_PINS): cv.All([pins.input_pin], cv.Length(min=8, max=8)), | ||||
|     cv.Required(CONF_VSYNC_PIN): pins.input_pin, | ||||
| @@ -80,7 +80,7 @@ CONFIG_SCHEMA = cv.Schema({ | ||||
|                                                                        max=60)), | ||||
|     cv.Optional(CONF_IDLE_FRAMERATE, default='0.1 fps'): cv.All(cv.framerate, | ||||
|                                                                 cv.Range(min=0, max=1)), | ||||
|     cv.Optional(CONF_RESOLUTION, default='640X480'): cv.one_of(*FRAME_SIZES, upper=True), | ||||
|     cv.Optional(CONF_RESOLUTION, default='640X480'): cv.enum(FRAME_SIZES, upper=True), | ||||
|     cv.Optional(CONF_JPEG_QUALITY, default=10): cv.All(cv.int_, cv.Range(min=10, max=63)), | ||||
|     cv.Optional(CONF_CONTRAST, default=0): camera_range_param, | ||||
|     cv.Optional(CONF_BRIGHTNESS, default=0): camera_range_param, | ||||
| @@ -124,7 +124,7 @@ def to_code(config): | ||||
|         cg.add(var.set_idle_update_interval(0)) | ||||
|     else: | ||||
|         cg.add(var.set_idle_update_interval(1000 / config[CONF_IDLE_FRAMERATE])) | ||||
|     cg.add(var.set_frame_size(FRAME_SIZES[config[CONF_RESOLUTION]])) | ||||
|     cg.add(var.set_frame_size(config[CONF_RESOLUTION])) | ||||
|  | ||||
|     cg.add_define('USE_ESP32_CAMERA') | ||||
|     cg.add_build_flag('-DBOARD_HAS_PSRAM') | ||||
|   | ||||
| @@ -1,22 +1,18 @@ | ||||
| from esphome.components import sensor | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome.components import sensor | ||||
| from esphome.const import CONF_ID, CONF_NAME, CONF_UPDATE_INTERVAL, ESP_PLATFORM_ESP32, \ | ||||
|     CONF_UNIT_OF_MEASUREMENT, CONF_ICON, CONF_ACCURACY_DECIMALS, UNIT_MICROTESLA, ICON_MAGNET | ||||
|     UNIT_MICROTESLA, ICON_MAGNET | ||||
|  | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
|  | ||||
| esp32_hall_ns = cg.esphome_ns.namespace('esp32_hall') | ||||
| ESP32HallSensor = esp32_hall_ns.class_('ESP32HallSensor', sensor.PollingSensorComponent) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(sensor.SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32HallSensor), | ||||
| CONFIG_SCHEMA = sensor.sensor_schema(UNIT_MICROTESLA, ICON_MAGNET, 1).extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32HallSensor), | ||||
|     cv.Optional(CONF_UPDATE_INTERVAL, default='60s'): cv.update_interval, | ||||
|  | ||||
|     cv.Optional(CONF_UNIT_OF_MEASUREMENT, default=UNIT_MICROTESLA): sensor.unit_of_measurement, | ||||
|     cv.Optional(CONF_ICON, default=ICON_MAGNET): sensor.icon, | ||||
|     cv.Optional(CONF_ACCURACY_DECIMALS, default=-1): sensor.accuracy_decimals, | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -44,7 +44,7 @@ VOLTAGE_ATTENUATION = { | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32TouchComponent), | ||||
|     cv.GenerateID(): cv.declare_id(ESP32TouchComponent), | ||||
|     cv.Optional(CONF_SETUP_MODE, default=False): cv.boolean, | ||||
|     cv.Optional(CONF_IIR_FILTER, default='0ms'): cv.positive_time_period_milliseconds, | ||||
|     cv.Optional(CONF_SLEEP_DURATION, default='27306us'): | ||||
|   | ||||
| @@ -34,12 +34,12 @@ def validate_touch_pad(value): | ||||
|  | ||||
| ESP32TouchBinarySensor = esp32_touch_ns.class_('ESP32TouchBinarySensor', binary_sensor.BinarySensor) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(ESP32TouchBinarySensor), | ||||
|     cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_variable_id(ESP32TouchComponent), | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(ESP32TouchBinarySensor), | ||||
|     cv.GenerateID(CONF_ESP32_TOUCH_ID): cv.use_id(ESP32TouchComponent), | ||||
|     cv.Required(CONF_PIN): validate_touch_pad, | ||||
|     cv.Required(CONF_THRESHOLD): cv.uint16_t, | ||||
| })) | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -25,6 +25,8 @@ void ESP8266PWM::dump_config() { | ||||
|   LOG_FLOAT_OUTPUT(this); | ||||
| } | ||||
| void HOT ESP8266PWM::write_state(float state) { | ||||
|   this->last_output_ = state; | ||||
|  | ||||
|   // Also check pin inversion | ||||
|   if (this->pin_->is_inverted()) { | ||||
|     state = 1.0f - state; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| #include "esphome/core/component.h" | ||||
| #include "esphome/core/esphal.h" | ||||
| #include "esphome/core/automation.h" | ||||
| #include "esphome/components/output/float_output.h" | ||||
|  | ||||
| namespace esphome { | ||||
| @@ -9,9 +10,13 @@ namespace esp8266_pwm { | ||||
|  | ||||
| class ESP8266PWM : public output::FloatOutput, public Component { | ||||
|  public: | ||||
|   explicit ESP8266PWM(GPIOPin *pin) : pin_(pin) {} | ||||
|  | ||||
|   void set_pin(GPIOPin *pin) { pin_ = pin; } | ||||
|   void set_frequency(float frequency) { this->frequency_ = frequency; } | ||||
|   /// Dynamically update frequency | ||||
|   void update_frequency(float frequency) { | ||||
|     this->set_frequency(frequency); | ||||
|     this->write_state(this->last_output_); | ||||
|   } | ||||
|  | ||||
|   /// Initialize pin | ||||
|   void setup() override; | ||||
| @@ -24,6 +29,22 @@ class ESP8266PWM : public output::FloatOutput, public Component { | ||||
|  | ||||
|   GPIOPin *pin_; | ||||
|   float frequency_{1000.0}; | ||||
|   /// Cache last output level for dynamic frequency updating | ||||
|   float last_output_{0.0}; | ||||
| }; | ||||
|  | ||||
| template<typename... Ts> class SetFrequencyAction : public Action<Ts...> { | ||||
|  public: | ||||
|   SetFrequencyAction(ESP8266PWM *parent) : parent_(parent) {} | ||||
|   TEMPLATABLE_VALUE(float, frequency); | ||||
|  | ||||
|   void play(Ts... x) { | ||||
|     float freq = this->frequency_.value(x...); | ||||
|     this->parent_->update_frequency(freq); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
|   ESP8266PWM *parent_; | ||||
| }; | ||||
|  | ||||
| }  // namespace esp8266_pwm | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| from esphome import pins | ||||
| from esphome import pins, automation | ||||
| from esphome.components import output | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| @@ -15,18 +15,34 @@ def valid_pwm_pin(value): | ||||
|  | ||||
| esp8266_pwm_ns = cg.esphome_ns.namespace('esp8266_pwm') | ||||
| ESP8266PWM = esp8266_pwm_ns.class_('ESP8266PWM', output.FloatOutput, cg.Component) | ||||
| SetFrequencyAction = esp8266_pwm_ns.class_('SetFrequencyAction', automation.Action) | ||||
| validate_frequency = cv.All(cv.frequency, cv.Range(min=1.0e-6)) | ||||
|  | ||||
| CONFIG_SCHEMA = output.FLOAT_OUTPUT_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_variable_id(ESP8266PWM), | ||||
|     cv.Required(CONF_ID): cv.declare_id(ESP8266PWM), | ||||
|     cv.Required(CONF_PIN): cv.All(pins.internal_gpio_output_pin_schema, valid_pwm_pin), | ||||
|     cv.Optional(CONF_FREQUENCY, default='1kHz'): cv.All(cv.frequency, cv.Range(min=1.0e-6)), | ||||
|     cv.Optional(CONF_FREQUENCY, default='1kHz'): validate_frequency, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID], pin) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield output.register_output(var, config) | ||||
|  | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|  | ||||
|     cg.add(var.set_frequency(config[CONF_FREQUENCY])) | ||||
|  | ||||
|  | ||||
| @automation.register_action('output.esp8266_pwm.set_frequency', SetFrequencyAction, cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.use_id(ESP8266PWM), | ||||
|     cv.Required(CONF_FREQUENCY): cv.templatable(validate_frequency), | ||||
| })) | ||||
| def esp8266_set_frequency_to_code(config, action_id, template_arg, args): | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|     template_ = yield cg.templatable(config[CONF_FREQUENCY], args, float) | ||||
|     cg.add(var.set_frequency(template_)) | ||||
|     yield var | ||||
|   | ||||
| @@ -7,6 +7,7 @@ from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| CONFLICTS_WITH = ['wifi'] | ||||
| ESP_PLATFORMS = [ESP_PLATFORM_ESP32] | ||||
| AUTO_LOAD = ['network'] | ||||
|  | ||||
| ethernet_ns = cg.esphome_ns.namespace('ethernet') | ||||
| CONF_PHY_ADDR = 'phy_addr' | ||||
| @@ -54,12 +55,12 @@ def validate(config): | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(cv.Schema({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(EthernetComponent), | ||||
|     cv.Required(CONF_TYPE): cv.one_of(*ETHERNET_TYPES, upper=True), | ||||
|     cv.GenerateID(): cv.declare_id(EthernetComponent), | ||||
|     cv.Required(CONF_TYPE): cv.enum(ETHERNET_TYPES, upper=True), | ||||
|     cv.Required(CONF_MDC_PIN): pins.output_pin, | ||||
|     cv.Required(CONF_MDIO_PIN): pins.input_output_pin, | ||||
|     cv.Optional(CONF_CLK_MODE, default='GPIO0_IN'): cv.one_of(*CLK_MODES, upper=True, space='_'), | ||||
|     cv.Optional(CONF_PHY_ADDR, default=0): cv.All(cv.int_, cv.Range(min=0, max=31)), | ||||
|     cv.Optional(CONF_CLK_MODE, default='GPIO0_IN'): cv.enum(CLK_MODES, upper=True, space='_'), | ||||
|     cv.Optional(CONF_PHY_ADDR, default=0): cv.int_range(min=0, max=31), | ||||
|     cv.Optional(CONF_POWER_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_MANUAL_IP): MANUAL_IP_SCHEMA, | ||||
|     cv.Optional(CONF_DOMAIN, default='.local'): cv.domain_name, | ||||
| @@ -87,7 +88,7 @@ def to_code(config): | ||||
|     cg.add(var.set_phy_addr(config[CONF_PHY_ADDR])) | ||||
|     cg.add(var.set_mdc_pin(config[CONF_MDC_PIN])) | ||||
|     cg.add(var.set_mdio_pin(config[CONF_MDIO_PIN])) | ||||
|     cg.add(var.set_type(ETHERNET_TYPES[config[CONF_TYPE]])) | ||||
|     cg.add(var.set_type(config[CONF_TYPE])) | ||||
|     cg.add(var.set_clk_mode(CLK_MODES[config[CONF_CLK_MODE]])) | ||||
|     cg.add(var.set_use_address(config[CONF_USE_ADDRESS])) | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| from esphome.automation import ACTION_REGISTRY, maybe_simple_id | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import maybe_simple_id | ||||
| from esphome.components import mqtt | ||||
| from esphome.const import CONF_ID, CONF_INTERNAL, CONF_MQTT_ID, CONF_OSCILLATING, \ | ||||
|     CONF_OSCILLATION_COMMAND_TOPIC, CONF_OSCILLATION_STATE_TOPIC, CONF_SPEED, \ | ||||
| @@ -14,9 +15,9 @@ FanState = fan_ns.class_('FanState', cg.Nameable, cg.Component) | ||||
| MakeFan = cg.Application.struct('MakeFan') | ||||
|  | ||||
| # Actions | ||||
| TurnOnAction = fan_ns.class_('TurnOnAction', cg.Action) | ||||
| TurnOffAction = fan_ns.class_('TurnOffAction', cg.Action) | ||||
| ToggleAction = fan_ns.class_('ToggleAction', cg.Action) | ||||
| TurnOnAction = fan_ns.class_('TurnOnAction', automation.Action) | ||||
| TurnOffAction = fan_ns.class_('TurnOffAction', automation.Action) | ||||
| ToggleAction = fan_ns.class_('ToggleAction', automation.Action) | ||||
|  | ||||
| FanSpeed = fan_ns.enum('FanSpeed') | ||||
| FAN_SPEEDS = { | ||||
| @@ -27,8 +28,8 @@ FAN_SPEEDS = { | ||||
| } | ||||
|  | ||||
| FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(FanState), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_variable_id(mqtt.MQTTFanComponent), | ||||
|     cv.GenerateID(): cv.declare_id(FanState), | ||||
|     cv.OnlyWith(CONF_MQTT_ID, 'mqtt'): cv.declare_id(mqtt.MQTTFanComponent), | ||||
|     cv.Optional(CONF_OSCILLATION_STATE_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
|                                                       cv.publish_topic), | ||||
|     cv.Optional(CONF_OSCILLATION_COMMAND_TOPIC): cv.All(cv.requires_component('mqtt'), | ||||
| @@ -38,6 +39,7 @@ FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend({ | ||||
|  | ||||
| @coroutine | ||||
| def setup_fan_core_(var, config): | ||||
|     cg.add(var.set_name(config[CONF_NAME])) | ||||
|     if CONF_INTERNAL in config: | ||||
|         cg.add(var.set_internal(config[CONF_INTERNAL])) | ||||
|  | ||||
| @@ -66,50 +68,43 @@ def register_fan(var, config): | ||||
|  | ||||
| @coroutine | ||||
| def create_fan_state(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID], config[CONF_NAME]) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield register_fan(var, config) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| FAN_ACTION_SCHEMA = maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(FanState), | ||||
|     cv.Required(CONF_ID): cv.use_id(FanState), | ||||
| }) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('fan.toggle', FAN_ACTION_SCHEMA) | ||||
| @automation.register_action('fan.toggle', ToggleAction, FAN_ACTION_SCHEMA) | ||||
| def fan_toggle_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = ToggleAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('fan.turn_off', FAN_ACTION_SCHEMA) | ||||
| @automation.register_action('fan.turn_off', TurnOffAction, FAN_ACTION_SCHEMA) | ||||
| def fan_turn_off_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = TurnOffAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     yield cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     yield cg.new_Pvariable(action_id, template_arg, paren) | ||||
|  | ||||
|  | ||||
| @ACTION_REGISTRY.register('fan.turn_on', maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_variable_id(FanState), | ||||
| @automation.register_action('fan.turn_on', TurnOnAction, maybe_simple_id({ | ||||
|     cv.Required(CONF_ID): cv.use_id(FanState), | ||||
|     cv.Optional(CONF_OSCILLATING): cv.templatable(cv.boolean), | ||||
|     cv.Optional(CONF_SPEED): cv.templatable(cv.one_of(*FAN_SPEEDS, upper=True)), | ||||
|     cv.Optional(CONF_SPEED): cv.templatable(cv.enum(FAN_SPEEDS, upper=True)), | ||||
| })) | ||||
| def fan_turn_on_to_code(config, action_id, template_arg, args): | ||||
|     var = yield cg.get_variable(config[CONF_ID]) | ||||
|     type = TurnOnAction.template(template_arg) | ||||
|     rhs = type.new(var) | ||||
|     action = cg.Pvariable(action_id, rhs, type=type) | ||||
|     paren = yield cg.get_variable(config[CONF_ID]) | ||||
|     var = cg.new_Pvariable(action_id, template_arg, paren) | ||||
|     if CONF_OSCILLATING in config: | ||||
|         template_ = yield cg.templatable(config[CONF_OSCILLATING], args, bool) | ||||
|         cg.add(action.set_oscillating(template_)) | ||||
|         cg.add(var.set_oscillating(template_)) | ||||
|     if CONF_SPEED in config: | ||||
|         template_ = yield cg.templatable(config[CONF_SPEED], args, FanSpeed, | ||||
|                                          to_exp=FAN_SPEEDS) | ||||
|         cg.add(action.set_speed(template_)) | ||||
|     yield action | ||||
|         template_ = yield cg.templatable(config[CONF_SPEED], args, FanSpeed) | ||||
|         cg.add(var.set_speed(template_)) | ||||
|     yield var | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -23,7 +23,6 @@ template<typename... Ts> class TurnOnAction : public Action<Ts...> { | ||||
|       call.set_speed(this->speed_.value(x...)); | ||||
|     } | ||||
|     call.perform(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|  | ||||
|  protected: | ||||
| @@ -34,10 +33,7 @@ template<typename... Ts> class TurnOffAction : public Action<Ts...> { | ||||
|  public: | ||||
|   explicit TurnOffAction(FanState *state) : state_(state) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->state_->turn_off().perform(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->state_->turn_off().perform(); } | ||||
|  | ||||
|  protected: | ||||
|   FanState *state_; | ||||
| @@ -47,10 +43,7 @@ template<typename... Ts> class ToggleAction : public Action<Ts...> { | ||||
|  public: | ||||
|   explicit ToggleAction(FanState *state) : state_(state) {} | ||||
|  | ||||
|   void play(Ts... x) override { | ||||
|     this->state_->toggle().perform(); | ||||
|     this->play_next(x...); | ||||
|   } | ||||
|   void play(Ts... x) override { this->state_->toggle().perform(); } | ||||
|  | ||||
|  protected: | ||||
|   FanState *state_; | ||||
|   | ||||
| @@ -13,10 +13,10 @@ void FanState::add_on_state_callback(std::function<void()> &&callback) { | ||||
| } | ||||
| FanState::FanState(const std::string &name) : Nameable(name) {} | ||||
|  | ||||
| FanState::StateCall FanState::turn_on() { return this->make_call().set_state(true); } | ||||
| FanState::StateCall FanState::turn_off() { return this->make_call().set_state(false); } | ||||
| FanState::StateCall FanState::toggle() { return this->make_call().set_state(!this->state); } | ||||
| FanState::StateCall FanState::make_call() { return FanState::StateCall(this); } | ||||
| FanStateCall FanState::turn_on() { return this->make_call().set_state(true); } | ||||
| FanStateCall FanState::turn_off() { return this->make_call().set_state(false); } | ||||
| FanStateCall FanState::toggle() { return this->make_call().set_state(!this->state); } | ||||
| FanStateCall FanState::make_call() { return FanStateCall(this); } | ||||
|  | ||||
| struct FanStateRTCState { | ||||
|   bool state; | ||||
| @@ -39,32 +39,7 @@ void FanState::setup() { | ||||
| float FanState::get_setup_priority() const { return setup_priority::HARDWARE - 1.0f; } | ||||
| uint32_t FanState::hash_base() { return 418001110UL; } | ||||
|  | ||||
| FanState::StateCall::StateCall(FanState *state) : state_(state) {} | ||||
| FanState::StateCall &FanState::StateCall::set_state(bool state) { | ||||
|   this->binary_state_ = state; | ||||
|   return *this; | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_state(optional<bool> state) { | ||||
|   this->binary_state_ = state; | ||||
|   return *this; | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_oscillating(bool oscillating) { | ||||
|   this->oscillating_ = oscillating; | ||||
|   return *this; | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_oscillating(optional<bool> oscillating) { | ||||
|   this->oscillating_ = oscillating; | ||||
|   return *this; | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_speed(FanSpeed speed) { | ||||
|   this->speed_ = speed; | ||||
|   return *this; | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_speed(optional<FanSpeed> speed) { | ||||
|   this->speed_ = speed; | ||||
|   return *this; | ||||
| } | ||||
| void FanState::StateCall::perform() const { | ||||
| void FanStateCall::perform() const { | ||||
|   if (this->binary_state_.has_value()) { | ||||
|     this->state_->state = *this->binary_state_; | ||||
|   } | ||||
| @@ -92,7 +67,7 @@ void FanState::StateCall::perform() const { | ||||
|  | ||||
|   this->state_->state_callback_.call(); | ||||
| } | ||||
| FanState::StateCall &FanState::StateCall::set_speed(const char *speed) { | ||||
| FanStateCall &FanStateCall::set_speed(const char *speed) { | ||||
|   if (strcasecmp(speed, "low") == 0) { | ||||
|     this->set_speed(FAN_SPEED_LOW); | ||||
|   } else if (strcasecmp(speed, "medium") == 0) { | ||||
|   | ||||
| @@ -15,8 +15,50 @@ enum FanSpeed { | ||||
|   FAN_SPEED_HIGH = 2     ///< The fan is running on high/full speed. | ||||
| }; | ||||
|  | ||||
| class FanState; | ||||
|  | ||||
| class FanStateCall { | ||||
|  public: | ||||
|   explicit FanStateCall(FanState *state) : state_(state) {} | ||||
|  | ||||
|   FanStateCall &set_state(bool binary_state) { | ||||
|     this->binary_state_ = binary_state; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_state(optional<bool> binary_state) { | ||||
|     this->binary_state_ = binary_state; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_oscillating(bool oscillating) { | ||||
|     this->oscillating_ = oscillating; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_oscillating(optional<bool> oscillating) { | ||||
|     this->oscillating_ = oscillating; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_speed(FanSpeed speed) { | ||||
|     this->speed_ = speed; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_speed(optional<FanSpeed> speed) { | ||||
|     this->speed_ = speed; | ||||
|     return *this; | ||||
|   } | ||||
|   FanStateCall &set_speed(const char *speed); | ||||
|  | ||||
|   void perform() const; | ||||
|  | ||||
|  protected: | ||||
|   FanState *const state_; | ||||
|   optional<bool> binary_state_; | ||||
|   optional<bool> oscillating_{}; | ||||
|   optional<FanSpeed> speed_{}; | ||||
| }; | ||||
|  | ||||
| class FanState : public Nameable, public Component { | ||||
|  public: | ||||
|   FanState() = default; | ||||
|   /// Construct the fan state with name. | ||||
|   explicit FanState(const std::string &name); | ||||
|  | ||||
| @@ -35,36 +77,17 @@ class FanState : public Nameable, public Component { | ||||
|   /// The current fan speed. | ||||
|   FanSpeed speed{FAN_SPEED_HIGH}; | ||||
|  | ||||
|   class StateCall { | ||||
|    public: | ||||
|     explicit StateCall(FanState *state); | ||||
|  | ||||
|     FanState::StateCall &set_state(bool state); | ||||
|     FanState::StateCall &set_state(optional<bool> state); | ||||
|     FanState::StateCall &set_oscillating(bool oscillating); | ||||
|     FanState::StateCall &set_oscillating(optional<bool> oscillating); | ||||
|     FanState::StateCall &set_speed(FanSpeed speed); | ||||
|     FanState::StateCall &set_speed(optional<FanSpeed> speed); | ||||
|     FanState::StateCall &set_speed(const char *speed); | ||||
|  | ||||
|     void perform() const; | ||||
|  | ||||
|    protected: | ||||
|     FanState *const state_; | ||||
|     optional<bool> binary_state_; | ||||
|     optional<bool> oscillating_{}; | ||||
|     optional<FanSpeed> speed_{}; | ||||
|   }; | ||||
|  | ||||
|   FanState::StateCall turn_on(); | ||||
|   FanState::StateCall turn_off(); | ||||
|   FanState::StateCall toggle(); | ||||
|   FanState::StateCall make_call(); | ||||
|   FanStateCall turn_on(); | ||||
|   FanStateCall turn_off(); | ||||
|   FanStateCall toggle(); | ||||
|   FanStateCall make_call(); | ||||
|  | ||||
|   void setup() override; | ||||
|   float get_setup_priority() const override; | ||||
|  | ||||
|  protected: | ||||
|   friend FanStateCall; | ||||
|  | ||||
|   uint32_t hash_base() override; | ||||
|  | ||||
|   FanTraits traits_{}; | ||||
|   | ||||
| @@ -19,13 +19,13 @@ RGB_ORDERS = [ | ||||
| ] | ||||
|  | ||||
| BASE_SCHEMA = light.ADDRESSABLE_LIGHT_SCHEMA.extend({ | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_variable_id(FastLEDLightOutput), | ||||
|     cv.GenerateID(CONF_OUTPUT_ID): cv.declare_id(FastLEDLightOutput), | ||||
|  | ||||
|     cv.Required(CONF_NUM_LEDS): cv.positive_not_null_int, | ||||
|     cv.Optional(CONF_RGB_ORDER): cv.one_of(*RGB_ORDERS, upper=True), | ||||
|     cv.Optional(CONF_MAX_REFRESH_RATE): cv.positive_time_period_microseconds, | ||||
|  | ||||
|     cv.Optional(CONF_POWER_SUPPLY): cv.use_variable_id(power_supply.PowerSupply), | ||||
|     cv.Optional(CONF_POWER_SUPPLY): cv.use_id(power_supply.PowerSupply), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -38,7 +38,7 @@ def validate(value): | ||||
|     return value | ||||
|  | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(fastled_base.BASE_SCHEMA.extend({ | ||||
| CONFIG_SCHEMA = cv.All(fastled_base.BASE_SCHEMA.extend({ | ||||
|     cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|     cv.Required(CONF_PIN): pins.output_pin, | ||||
| }), validate) | ||||
|   | ||||
| @@ -17,11 +17,11 @@ CHIPSETS = [ | ||||
|     'DOTSTAR', | ||||
| ] | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(fastled_base.BASE_SCHEMA.extend({ | ||||
| CONFIG_SCHEMA = fastled_base.BASE_SCHEMA.extend({ | ||||
|     cv.Required(CONF_CHIPSET): cv.one_of(*CHIPSETS, upper=True), | ||||
|     cv.Required(CONF_DATA_PIN): pins.output_pin, | ||||
|     cv.Required(CONF_CLOCK_PIN): pins.output_pin, | ||||
| })) | ||||
| }) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|   | ||||
| @@ -67,11 +67,11 @@ DEFAULT_GLYPHS = u' !"%()+,-.:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklm | ||||
| CONF_RAW_DATA_ID = 'raw_data_id' | ||||
|  | ||||
| FONT_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.declare_variable_id(Font), | ||||
|     cv.Required(CONF_ID): cv.declare_id(Font), | ||||
|     cv.Required(CONF_FILE): validate_truetype_file, | ||||
|     cv.Optional(CONF_GLYPHS, default=DEFAULT_GLYPHS): validate_glyphs, | ||||
|     cv.Optional(CONF_SIZE, default=20): cv.All(cv.int_, cv.Range(min=1)), | ||||
|     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_variable_id(cg.uint8), | ||||
|     cv.GenerateID(CONF_RAW_DATA_ID): cv.declare_id(cg.uint8), | ||||
| }) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA) | ||||
| @@ -80,7 +80,7 @@ CONFIG_SCHEMA = cv.All(validate_pillow_installed, FONT_SCHEMA) | ||||
| def to_code(config): | ||||
|     from PIL import ImageFont | ||||
|  | ||||
|     path = CORE.relative_path(config[CONF_FILE]) | ||||
|     path = CORE.relative_config_path(config[CONF_FILE]) | ||||
|     try: | ||||
|         font = ImageFont.truetype(path, config[CONF_SIZE]) | ||||
|     except Exception as e: | ||||
|   | ||||
| @@ -11,7 +11,7 @@ GlobalsComponent = globals_ns.class_('GlobalsComponent', cg.Component) | ||||
| MULTI_CONF = True | ||||
|  | ||||
| CONFIG_SCHEMA = cv.Schema({ | ||||
|     cv.Required(CONF_ID): cv.declare_variable_id(GlobalsComponent), | ||||
|     cv.Required(CONF_ID): cv.declare_id(GlobalsComponent), | ||||
|     cv.Required(CONF_TYPE): cv.string_strict, | ||||
|     cv.Optional(CONF_INITIAL_VALUE): cv.string_strict, | ||||
|     cv.Optional(CONF_RESTORE_VALUE): cv.boolean, | ||||
|   | ||||
| @@ -2,20 +2,21 @@ import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import binary_sensor | ||||
| from esphome.const import CONF_ID, CONF_NAME, CONF_PIN | ||||
| from esphome.const import CONF_ID, CONF_PIN | ||||
| from .. import gpio_ns | ||||
|  | ||||
| GPIOBinarySensor = gpio_ns.class_('GPIOBinarySensor', binary_sensor.BinarySensor, cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(GPIOBinarySensor), | ||||
| CONFIG_SCHEMA = binary_sensor.BINARY_SENSOR_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(GPIOBinarySensor), | ||||
|     cv.Required(CONF_PIN): pins.gpio_input_pin_schema | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield binary_sensor.register_binary_sensor(var, config) | ||||
|  | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     rhs = GPIOBinarySensor.new(config[CONF_NAME], pin) | ||||
|     gpio = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(gpio, config) | ||||
|     yield binary_sensor.register_binary_sensor(gpio, config) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|   | ||||
| @@ -19,8 +19,6 @@ void GPIOBinarySensor::dump_config() { | ||||
| void GPIOBinarySensor::loop() { this->publish_state(this->pin_->digital_read()); } | ||||
|  | ||||
| float GPIOBinarySensor::get_setup_priority() const { return setup_priority::HARDWARE; } | ||||
| GPIOBinarySensor::GPIOBinarySensor(const std::string &name, GPIOPin *pin) | ||||
|     : binary_sensor::BinarySensor(name), pin_(pin) {} | ||||
|  | ||||
| }  // namespace gpio | ||||
| }  // namespace esphome | ||||
|   | ||||
| @@ -8,8 +8,7 @@ namespace gpio { | ||||
|  | ||||
| class GPIOBinarySensor : public binary_sensor::BinarySensor, public Component { | ||||
|  public: | ||||
|   explicit GPIOBinarySensor(const std::string &name, GPIOPin *pin); | ||||
|  | ||||
|   void set_pin(GPIOPin *pin) { pin_ = pin; } | ||||
|   // ========== INTERNAL METHODS ========== | ||||
|   // (In most use cases you won't need these) | ||||
|   /// Setup pin | ||||
|   | ||||
| @@ -9,13 +9,15 @@ GPIOBinaryOutput = gpio_ns.class_('GPIOBinaryOutput', output.BinaryOutput, | ||||
|                                   cg.Component) | ||||
|  | ||||
| CONFIG_SCHEMA = output.BINARY_OUTPUT_SCHEMA.extend({ | ||||
|     cv.Required(CONF_ID): cv.declare_variable_id(GPIOBinaryOutput), | ||||
|     cv.Required(CONF_ID): cv.declare_id(GPIOBinaryOutput), | ||||
|     cv.Required(CONF_PIN): pins.gpio_output_pin_schema, | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield output.register_output(var, config) | ||||
|     yield cg.register_component(var, config) | ||||
|  | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     gpio = cg.new_Pvariable(config[CONF_ID], pin) | ||||
|     yield output.register_output(gpio, config) | ||||
|     yield cg.register_component(gpio, config) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|   | ||||
| @@ -9,7 +9,7 @@ namespace gpio { | ||||
|  | ||||
| class GPIOBinaryOutput : public output::BinaryOutput, public Component { | ||||
|  public: | ||||
|   explicit GPIOBinaryOutput(GPIOPin *pin) : pin_(pin) {} | ||||
|   void set_pin(GPIOPin *pin) { pin_ = pin; } | ||||
|  | ||||
|   void setup() override { | ||||
|     this->turn_off(); | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import switch | ||||
| from esphome.const import CONF_ID, CONF_INTERLOCK, CONF_NAME, CONF_PIN, CONF_RESTORE_MODE | ||||
| from esphome.const import CONF_ID, CONF_INTERLOCK, CONF_PIN, CONF_RESTORE_MODE | ||||
| from .. import gpio_ns | ||||
|  | ||||
| GPIOSwitch = gpio_ns.class_('GPIOSwitch', switch.Switch, cg.Component) | ||||
| @@ -15,27 +15,28 @@ RESTORE_MODES = { | ||||
|     'ALWAYS_ON': GPIOSwitchRestoreMode.GPIO_SWITCH_ALWAYS_ON, | ||||
| } | ||||
|  | ||||
| CONFIG_SCHEMA = cv.nameable(switch.SWITCH_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_variable_id(GPIOSwitch), | ||||
| CONFIG_SCHEMA = switch.SWITCH_SCHEMA.extend({ | ||||
|     cv.GenerateID(): cv.declare_id(GPIOSwitch), | ||||
|     cv.Required(CONF_PIN): pins.gpio_output_pin_schema, | ||||
|     cv.Optional(CONF_RESTORE_MODE, default='RESTORE_DEFAULT_OFF'): | ||||
|         cv.one_of(*RESTORE_MODES, upper=True, space='_'), | ||||
|     cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_variable_id(switch.Switch)), | ||||
| }).extend(cv.COMPONENT_SCHEMA)) | ||||
|         cv.enum(RESTORE_MODES, upper=True, space='_'), | ||||
|     cv.Optional(CONF_INTERLOCK): cv.ensure_list(cv.use_id(switch.Switch)), | ||||
| }).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
|  | ||||
| def to_code(config): | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     rhs = GPIOSwitch.new(config[CONF_NAME], pin) | ||||
|     gpio = cg.Pvariable(config[CONF_ID], rhs) | ||||
|     yield cg.register_component(gpio, config) | ||||
|     yield switch.register_switch(gpio, config) | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
|     yield cg.register_component(var, config) | ||||
|     yield switch.register_switch(var, config) | ||||
|  | ||||
|     cg.add(gpio.set_restore_mode(RESTORE_MODES[config[CONF_RESTORE_MODE]])) | ||||
|     pin = yield cg.gpio_pin_expression(config[CONF_PIN]) | ||||
|     cg.add(var.set_pin(pin)) | ||||
|  | ||||
|     cg.add(var.set_restore_mode(config[CONF_RESTORE_MODE])) | ||||
|  | ||||
|     if CONF_INTERLOCK in config: | ||||
|         interlock = [] | ||||
|         for it in config[CONF_INTERLOCK]: | ||||
|             lock = yield cg.get_variable(it) | ||||
|             interlock.append(lock) | ||||
|         cg.add(gpio.set_interlock(interlock)) | ||||
|         cg.add(var.set_interlock(interlock)) | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user