From d5cf4b7eace9c02d8344aaea7644e81c1dc988dc Mon Sep 17 00:00:00 2001 From: Guillermo Ruffino Date: Sun, 7 Mar 2021 19:59:32 -0300 Subject: [PATCH] Improve error checking: too many component id candidates (#1570) * add error too many candidates * Improve error checking of ids --- esphome/__main__.py | 2 ++ esphome/config.py | 43 ++++++++++++++++++++++++++++++++++++------- tests/test1.yaml | 43 ++++++++++++++++++++++++++++++------------- tests/test3.yaml | 5 ----- 4 files changed, 68 insertions(+), 25 deletions(-) diff --git a/esphome/__main__.py b/esphome/__main__.py index 2acd16cf95..20cb44d11c 100644 --- a/esphome/__main__.py +++ b/esphome/__main__.py @@ -320,6 +320,8 @@ def command_config(args, config): def command_vscode(args): from esphome import vscode + logging.disable(logging.INFO) + logging.disable(logging.WARNING) CORE.config_path = args.configuration[0] vscode.read_config(args) diff --git a/esphome/config.py b/esphome/config.py index 995861fa6e..3317196965 100644 --- a/esphome/config.py +++ b/esphome/config.py @@ -282,12 +282,19 @@ class Config(OrderedDict): if item_index in data: doc_range = [x for x in data.keys() if x == item_index][0].esp_range data = data[item_index] - except (KeyError, IndexError, TypeError): + except (KeyError, IndexError, TypeError, AttributeError): return doc_range if isinstance(data, core.ID): data = data.id if isinstance(data, ESPHomeDataBase) and data.esp_range is not None: doc_range = data.esp_range + elif isinstance(data, dict): + platform_item = data.get("platform") + if ( + isinstance(platform_item, ESPHomeDataBase) + and platform_item.esp_range is not None + ): + doc_range = platform_item.esp_range return doc_range @@ -359,7 +366,7 @@ def do_id_pass(result): # type: (Config) -> None if id.id is not None: # manually declared match = next((v[0] for v in declare_ids if v[0].id == id.id), None) - if match is None: + if match is None or not match.is_manual: # No declared ID with this name import difflib @@ -369,7 +376,7 @@ def do_id_pass(result): # type: (Config) -> None ) # Find candidates matches = difflib.get_close_matches( - id.id, [v[0].id for v in declare_ids] + id.id, [v[0].id for v in declare_ids if v[0].is_manual] ) if matches: matches_s = ", ".join(f'"{x}"' for x in matches) @@ -389,15 +396,37 @@ def do_id_pass(result): # type: (Config) -> None ) if id.id is None and id.type is not None: + matches = [] for v in declare_ids: if v[0] is None or not isinstance(v[0].type, MockObjClass): continue inherits = v[0].type.inherits_from(id.type) if inherits: - id.id = v[0].id - break - else: - result.add_str_error(f"Couldn't resolve ID for type '{id.type}'", path) + matches.append(v[0]) + + if len(matches) == 0: + result.add_str_error( + f"Couldn't find any component that can be used for '{id.type}'. Are you missing a hub declaration?", + path, + ) + elif len(matches) == 1: + id.id = matches[0].id + elif len(matches) > 1: + if str(id.type) == "time::RealTimeClock": + id.id = matches[0].id + else: + manual_declared_count = sum(1 for m in matches if m.is_manual) + if manual_declared_count > 0: + ids = ", ".join([f"'{m.id}'" for m in matches if m.is_manual]) + result.add_str_error( + f"Too many candidates found for '{path[-1]}' type '{id.type}' {'Some are' if manual_declared_count > 1 else 'One is'} {ids}", + path, + ) + else: + result.add_str_error( + f"Too many candidates found for '{path[-1]}' type '{id.type}' You must assign an explicit ID to the parent component you want to use.", + path, + ) def recursive_check_replaceme(value): diff --git a/tests/test1.yaml b/tests/test1.yaml index 7651505c9a..f5c3ab9b57 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -144,9 +144,13 @@ mqtt: - uart.write: id: uart0 data: Hello World - - uart.write: [0x00, 0x20, 0x30] - - uart.write: !lambda |- - return {}; + - uart.write: + id: uart0 + data: [0x00, 0x20, 0x30] + - uart.write: + id: uart0 + data: !lambda |- + return {}; i2c: sda: 21 @@ -469,7 +473,7 @@ sensor: name: 'HLW8012 Power' id: hlw8012_power energy: - name: "HLW8012 Energy" + name: 'HLW8012 Energy' id: hlw8012_energy update_interval: 15s current_resistor: 0.001 ohm @@ -583,6 +587,7 @@ sensor: reference_resistance: '430 Ω' rtd_nominal_resistance: '100 Ω' - platform: mhz19 + uart_id: uart0 co2: name: 'MH-Z19 CO2 Value' temperature: @@ -648,25 +653,27 @@ sensor: name: Pulse Width pin: GPIO12 - platform: senseair + uart_id: uart0 co2: name: 'SenseAir CO2 Value' update_interval: 15s - platform: sm300d2 + uart_id: uart0 co2: - name: "SM300D2 CO2 Value" + name: 'SM300D2 CO2 Value' formaldehyde: - name: "SM300D2 Formaldehyde Value" + name: 'SM300D2 Formaldehyde Value' tvoc: - name: "SM300D2 TVOC Value" + name: 'SM300D2 TVOC Value' pm_2_5: - name: "SM300D2 PM2.5 Value" + name: 'SM300D2 PM2.5 Value' pm_10_0: - name: "SM300D2 PM10 Value" + name: 'SM300D2 PM10 Value' temperature: - name: "SM300D2 Temperature Value" + name: 'SM300D2 Temperature Value' humidity: - name: "SM300D2 Humidity Value" - update_interval: 60s + name: 'SM300D2 Humidity Value' + update_interval: 60s - platform: sht3xd temperature: name: 'Living Room Temperature 8' @@ -785,6 +792,7 @@ sensor: root["key"] = id(the_sensor).state; root["greeting"] = "Hello World"; - platform: sds011 + uart_id: uart0 pm_2_5: name: 'SDS011 PM2.5' pm_10_0: @@ -834,6 +842,7 @@ sensor: name: 'AQI' calculation_type: 'CAQI' - platform: teleinfo + uart_id: uart0 tags: - tag_name: 'HCHC' sensor: @@ -1007,6 +1016,7 @@ binary_sensor: id: gpio_19 frequency: !lambda 'return 500.0;' - platform: pn532 + pn532_id: pn532_bs uid: 74-10-37-94 name: 'PN532 NFC Tag' - platform: rdm6300 @@ -1518,7 +1528,7 @@ switch: turn_on_action: remote_transmitter.transmit_samsung36: address: 0x0400 - command: 0x000E00FF + command: 0x000E00FF - platform: template name: Sony turn_on_action: @@ -1653,12 +1663,15 @@ switch: id: my_switch state: !lambda 'return false;' - platform: uart + uart_id: uart0 name: 'UART String Output' data: 'DataToSend' - platform: uart + uart_id: uart0 name: 'UART Bytes Output' data: [0xDE, 0xAD, 0xBE, 0xEF] - platform: uart + uart_id: uart0 name: 'UART Recurring Output' data: [0xDE, 0xAD, 0xBE, 0xEF] send_every: 1s @@ -1774,6 +1787,7 @@ display: lambda: |- it.print("1234"); - platform: nextion + uart_id: uart0 lambda: |- it.set_component_value("gauge", 50); it.set_component_text("textview", "Hello World!"); @@ -1901,6 +1915,7 @@ status_led: pin: GPIO2 pn532_spi: + id: pn532_bs cs_pin: GPIO23 update_interval: 1s on_tag: @@ -1913,6 +1928,7 @@ pn532_spi: pn532_i2c: rdm6300: + uart_id: uart0 rc522_spi: cs_pin: GPIO23 @@ -1928,6 +1944,7 @@ rc522_i2c: ESP_LOGD("main", "Found tag %s", x.c_str()); gps: + uart_id: uart0 time: - platform: sntp diff --git a/tests/test3.yaml b/tests/test3.yaml index f4efe1067d..ee95e9d35f 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -197,10 +197,6 @@ uart: rx_pin: GPIO3 baud_rate: 115200 - - id: adalight_uart - rx_pin: GPIO3 - baud_rate: 115200 - ota: safe_mode: True port: 3286 @@ -814,7 +810,6 @@ light: effects: - wled: - adalight: - uart_id: adalight_uart - e131: universe: 1 - platform: hbridge