import logging import esphome.config_validation as cv from esphome.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER from esphome.core import CORE from esphome.util import SimpleRegistry _LOGGER = logging.getLogger(__name__) ESP8266_BASE_PINS = { "A0": 17, "SS": 15, "MOSI": 13, "MISO": 12, "SCK": 14, "SDA": 4, "SCL": 5, "RX": 3, "TX": 1, } ESP8266_BOARD_PINS = { "d1": { "D0": 3, "D1": 1, "D2": 16, "D3": 5, "D4": 4, "D5": 14, "D6": 12, "D7": 13, "D8": 0, "D9": 2, "D10": 15, "D11": 13, "D12": 14, "D13": 14, "D14": 4, "D15": 5, "LED": 2, }, "d1_mini": { "D0": 16, "D1": 5, "D2": 4, "D3": 0, "D4": 2, "D5": 14, "D6": 12, "D7": 13, "D8": 15, "LED": 2, }, "d1_mini_lite": "d1_mini", "d1_mini_pro": "d1_mini", "esp01": {}, "esp01_1m": {}, "esp07": {}, "esp12e": {}, "esp210": {}, "esp8285": {}, "esp_wroom_02": {}, "espduino": {"LED": 16}, "espectro": {"LED": 15, "BUTTON": 2}, "espino": {"LED": 2, "LED_RED": 2, "LED_GREEN": 4, "LED_BLUE": 5, "BUTTON": 0}, "espinotee": {"LED": 16}, "espresso_lite_v1": {"LED": 16}, "espresso_lite_v2": {"LED": 2}, "gen4iod": {}, "heltec_wifi_kit_8": "d1_mini", "huzzah": { "LED": 0, "LED_RED": 0, "LED_BLUE": 2, "D4": 4, "D5": 5, "D12": 12, "D13": 13, "D14": 14, "D15": 15, "D16": 16, }, "inventone": {}, "modwifi": {}, "nodemcu": { "D0": 16, "D1": 5, "D2": 4, "D3": 0, "D4": 2, "D5": 14, "D6": 12, "D7": 13, "D8": 15, "D9": 3, "D10": 1, "LED": 16, }, "nodemcuv2": "nodemcu", "oak": { "P0": 2, "P1": 5, "P2": 0, "P3": 3, "P4": 1, "P5": 4, "P6": 15, "P7": 13, "P8": 12, "P9": 14, "P10": 16, "P11": 17, "LED": 5, }, "phoenix_v1": {"LED": 16}, "phoenix_v2": {"LED": 2}, "sparkfunBlynk": "thing", "thing": {"LED": 5, "SDA": 2, "SCL": 14}, "thingdev": "thing", "wifi_slot": {"LED": 2}, "wifiduino": { "D0": 3, "D1": 1, "D2": 2, "D3": 0, "D4": 4, "D5": 5, "D6": 16, "D7": 14, "D8": 12, "D9": 13, "D10": 15, "D11": 13, "D12": 12, "D13": 14, }, "wifinfo": { "LED": 12, "D0": 16, "D1": 5, "D2": 4, "D3": 0, "D4": 2, "D5": 14, "D6": 12, "D7": 13, "D8": 15, "D9": 3, "D10": 1, }, "wio_link": {"LED": 2, "GROVE": 15, "D0": 14, "D1": 12, "D2": 13, "BUTTON": 0}, "wio_node": {"LED": 2, "GROVE": 15, "D0": 3, "D1": 5, "BUTTON": 0}, "xinabox_cw01": {"SDA": 2, "SCL": 14, "LED": 5, "LED_RED": 12, "LED_GREEN": 13}, } FLASH_SIZE_1_MB = 2 ** 20 FLASH_SIZE_512_KB = FLASH_SIZE_1_MB // 2 FLASH_SIZE_2_MB = 2 * FLASH_SIZE_1_MB FLASH_SIZE_4_MB = 4 * FLASH_SIZE_1_MB FLASH_SIZE_16_MB = 16 * FLASH_SIZE_1_MB ESP8266_FLASH_SIZES = { "d1": FLASH_SIZE_4_MB, "d1_mini": FLASH_SIZE_4_MB, "d1_mini_lite": FLASH_SIZE_1_MB, "d1_mini_pro": FLASH_SIZE_16_MB, "esp01": FLASH_SIZE_512_KB, "esp01_1m": FLASH_SIZE_1_MB, "esp07": FLASH_SIZE_4_MB, "esp12e": FLASH_SIZE_4_MB, "esp210": FLASH_SIZE_4_MB, "esp8285": FLASH_SIZE_1_MB, "esp_wroom_02": FLASH_SIZE_2_MB, "espduino": FLASH_SIZE_4_MB, "espectro": FLASH_SIZE_4_MB, "espino": FLASH_SIZE_4_MB, "espinotee": FLASH_SIZE_4_MB, "espresso_lite_v1": FLASH_SIZE_4_MB, "espresso_lite_v2": FLASH_SIZE_4_MB, "gen4iod": FLASH_SIZE_512_KB, "heltec_wifi_kit_8": FLASH_SIZE_4_MB, "huzzah": FLASH_SIZE_4_MB, "inventone": FLASH_SIZE_4_MB, "modwifi": FLASH_SIZE_2_MB, "nodemcu": FLASH_SIZE_4_MB, "nodemcuv2": FLASH_SIZE_4_MB, "oak": FLASH_SIZE_4_MB, "phoenix_v1": FLASH_SIZE_4_MB, "phoenix_v2": FLASH_SIZE_4_MB, "sparkfunBlynk": FLASH_SIZE_4_MB, "thing": FLASH_SIZE_512_KB, "thingdev": FLASH_SIZE_512_KB, "wifi_slot": FLASH_SIZE_1_MB, "wifiduino": FLASH_SIZE_4_MB, "wifinfo": FLASH_SIZE_1_MB, "wio_link": FLASH_SIZE_4_MB, "wio_node": FLASH_SIZE_4_MB, "xinabox_cw01": FLASH_SIZE_4_MB, } ESP8266_LD_SCRIPTS = { FLASH_SIZE_512_KB: ("eagle.flash.512k0.ld", "eagle.flash.512k.ld"), FLASH_SIZE_1_MB: ("eagle.flash.1m0.ld", "eagle.flash.1m.ld"), FLASH_SIZE_2_MB: ("eagle.flash.2m.ld", "eagle.flash.2m.ld"), FLASH_SIZE_4_MB: ("eagle.flash.4m.ld", "eagle.flash.4m.ld"), FLASH_SIZE_16_MB: ("eagle.flash.16m.ld", "eagle.flash.16m14m.ld"), } ESP32_BASE_PINS = { "TX": 1, "RX": 3, "SDA": 21, "SCL": 22, "SS": 5, "MOSI": 23, "MISO": 19, "SCK": 18, "A0": 36, "A3": 39, "A4": 32, "A5": 33, "A6": 34, "A7": 35, "A10": 4, "A11": 0, "A12": 2, "A13": 15, "A14": 13, "A15": 12, "A16": 14, "A17": 27, "A18": 25, "A19": 26, "T0": 4, "T1": 0, "T2": 2, "T3": 15, "T4": 13, "T5": 12, "T6": 14, "T7": 27, "T8": 33, "T9": 32, "DAC1": 25, "DAC2": 26, "SVP": 36, "SVN": 39, } ESP32_BOARD_PINS = { "alksesp32": { "A0": 32, "A1": 33, "A2": 25, "A3": 26, "A4": 27, "A5": 14, "A6": 12, "A7": 15, "D0": 40, "D1": 41, "D10": 19, "D11": 21, "D12": 22, "D13": 23, "D2": 15, "D3": 2, "D4": 0, "D5": 4, "D6": 16, "D7": 17, "D8": 5, "D9": 18, "DHT_PIN": 26, "LED": 23, "L_B": 5, "L_G": 17, "L_R": 22, "L_RGB_B": 16, "L_RGB_G": 21, "L_RGB_R": 4, "L_Y": 23, "MISO": 22, "MOSI": 21, "PHOTO": 25, "PIEZO1": 19, "PIEZO2": 18, "POT1": 32, "POT2": 33, "S1": 4, "S2": 16, "S3": 18, "S4": 19, "S5": 21, "SCK": 23, "SCL": 14, "SDA": 27, "SS": 19, "SW1": 15, "SW2": 2, "SW3": 0, }, "bpi-bit": { "BUTTON_A": 35, "BUTTON_B": 27, "BUZZER": 25, "LIGHT_SENSOR1": 36, "LIGHT_SENSOR2": 39, "MPU9250_INT": 0, "P0": 25, "P1": 32, "P10": 26, "P11": 27, "P12": 2, "P13": 18, "P14": 19, "P15": 23, "P16": 5, "P19": 22, "P2": 33, "P20": 21, "P3": 13, "P4": 15, "P5": 35, "P6": 12, "P7": 14, "P8": 16, "P9": 17, "RGB_LED": 4, "TEMPERATURE_SENSOR": 34, }, "d-duino-32": { "D1": 5, "D10": 1, "D2": 4, "D3": 0, "D4": 2, "D5": 14, "D6": 12, "D7": 13, "D8": 15, "D9": 3, "MISO": 12, "MOSI": 13, "SCK": 14, "SCL": 4, "SDA": 5, "SS": 15, }, "esp-wrover-kit": {}, "esp32-devkitlipo": {}, "esp32-evb": { "BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13, "SS": 17, }, "esp32-gateway": {"BUTTON": 34, "LED": 33, "SCL": 16, "SDA": 32}, "esp32-poe-iso": { "BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13, }, "esp32-poe": {"BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13}, "esp32-pro": { "BUTTON": 34, "MISO": 15, "MOSI": 2, "SCK": 14, "SCL": 16, "SDA": 13, "SS": 17, }, "esp320": { "LED": 5, "MISO": 12, "MOSI": 13, "SCK": 14, "SCL": 14, "SDA": 2, "SS": 15, }, "esp32cam": {}, "esp32dev": {}, "esp32doit-devkit-v1": {"LED": 2}, "esp32thing": {"BUTTON": 0, "LED": 5, "SS": 2}, "esp32vn-iot-uno": {}, "espea32": {"BUTTON": 0, "LED": 5}, "espectro32": {"LED": 15, "SD_SS": 33}, "espino32": {"BUTTON": 0, "LED": 16}, "featheresp32": { "A0": 26, "A1": 25, "A10": 27, "A11": 12, "A12": 13, "A13": 35, "A2": 34, "A4": 36, "A5": 4, "A6": 14, "A7": 32, "A8": 15, "A9": 33, "Ax": 2, "LED": 13, "MOSI": 18, "RX": 16, "SCK": 5, "SDA": 23, "SS": 33, "TX": 17, }, "firebeetle32": {"LED": 2}, "fm-devkit": { "D0": 34, "D1": 35, "D10": 0, "D2": 32, "D3": 33, "D4": 27, "D5": 14, "D6": 12, "D7": 13, "D8": 15, "D9": 23, "I2S_DOUT": 22, "I2S_LRCLK": 25, "I2S_MCLK": 2, "I2S_SCLK": 26, "LED": 5, "SCL": 17, "SDA": 16, "SW1": 4, "SW2": 18, "SW3": 19, "SW4": 21, }, "frogboard": {}, "heltec_wifi_kit_32": { "A1": 37, "A2": 38, "BUTTON": 0, "LED": 25, "RST_OLED": 16, "SCL_OLED": 15, "SDA_OLED": 4, "Vext": 21, }, "heltec_wifi_lora_32": { "BUTTON": 0, "DIO0": 26, "DIO1": 33, "DIO2": 32, "LED": 25, "MOSI": 27, "RST_LoRa": 14, "RST_OLED": 16, "SCK": 5, "SCL_OLED": 15, "SDA_OLED": 4, "SS": 18, "Vext": 21, }, "heltec_wifi_lora_32_V2": { "BUTTON": 0, "DIO0": 26, "DIO1": 35, "DIO2": 34, "LED": 25, "MOSI": 27, "RST_LoRa": 14, "RST_OLED": 16, "SCK": 5, "SCL_OLED": 15, "SDA_OLED": 4, "SS": 18, "Vext": 21, }, "heltec_wireless_stick": { "BUTTON": 0, "DIO0": 26, "DIO1": 35, "DIO2": 34, "LED": 25, "MOSI": 27, "RST_LoRa": 14, "RST_OLED": 16, "SCK": 5, "SCL_OLED": 15, "SDA_OLED": 4, "SS": 18, "Vext": 21, }, "hornbill32dev": {"BUTTON": 0, "LED": 13}, "hornbill32minima": {"SS": 2}, "intorobot": { "A1": 39, "A2": 35, "A3": 25, "A4": 26, "A5": 14, "A6": 12, "A7": 15, "A8": 13, "A9": 2, "BUTTON": 0, "D0": 19, "D1": 23, "D2": 18, "D3": 17, "D4": 16, "D5": 5, "D6": 4, "LED": 4, "MISO": 17, "MOSI": 16, "RGB_B_BUILTIN": 22, "RGB_G_BUILTIN": 21, "RGB_R_BUILTIN": 27, "SCL": 19, "SDA": 23, "T0": 19, "T1": 23, "T2": 18, "T3": 17, "T4": 16, "T5": 5, "T6": 4, }, "iotaap_magnolia": {}, "iotbusio": {}, "iotbusproteus": {}, "lolin32": {"LED": 5}, "lolin32_lite": {"LED": 22}, "lolin_d32": {"LED": 5, "_VBAT": 35}, "lolin_d32_pro": {"LED": 5, "_VBAT": 35}, "lopy": { "A1": 37, "A2": 38, "LED": 0, "MISO": 37, "MOSI": 22, "SCK": 13, "SCL": 13, "SDA": 12, "SS": 17, }, "lopy4": { "A1": 37, "A2": 38, "LED": 0, "MISO": 37, "MOSI": 22, "SCK": 13, "SCL": 13, "SDA": 12, "SS": 18, }, "m5stack-core-esp32": { "ADC1": 35, "ADC2": 36, "G0": 0, "G1": 1, "G12": 12, "G13": 13, "G15": 15, "G16": 16, "G17": 17, "G18": 18, "G19": 19, "G2": 2, "G21": 21, "G22": 22, "G23": 23, "G25": 25, "G26": 26, "G3": 3, "G34": 34, "G35": 35, "G36": 36, "G5": 5, "RXD2": 16, "TXD2": 17, }, "m5stack-fire": { "ADC1": 35, "ADC2": 36, "G0": 0, "G1": 1, "G12": 12, "G13": 13, "G15": 15, "G16": 16, "G17": 17, "G18": 18, "G19": 19, "G2": 2, "G21": 21, "G22": 22, "G23": 23, "G25": 25, "G26": 26, "G3": 3, "G34": 34, "G35": 35, "G36": 36, "G5": 5, }, "m5stack-grey": { "ADC1": 35, "ADC2": 36, "G0": 0, "G1": 1, "G12": 12, "G13": 13, "G15": 15, "G16": 16, "G17": 17, "G18": 18, "G19": 19, "G2": 2, "G21": 21, "G22": 22, "G23": 23, "G25": 25, "G26": 26, "G3": 3, "G34": 34, "G35": 35, "G36": 36, "G5": 5, "RXD2": 16, "TXD2": 17, }, "m5stick-c": { "ADC1": 35, "ADC2": 36, "G0": 0, "G10": 10, "G26": 26, "G32": 32, "G33": 33, "G36": 36, "G37": 37, "G39": 39, "G9": 9, "MISO": 36, "MOSI": 15, "SCK": 13, "SCL": 33, "SDA": 32, }, "magicbit": { "BLUE_LED": 17, "BUZZER": 25, "GREEN_LED": 16, "LDR": 36, "LED": 16, "LEFT_BUTTON": 35, "MOTOR1A": 27, "MOTOR1B": 18, "MOTOR2A": 16, "MOTOR2B": 17, "POT": 39, "RED_LED": 27, "RIGHT_PUTTON": 34, "YELLOW_LED": 18, }, "mhetesp32devkit": {"LED": 2}, "mhetesp32minikit": {"LED": 2}, "microduino-core-esp32": { "A0": 12, "A1": 13, "A10": 25, "A11": 26, "A12": 27, "A13": 14, "A2": 15, "A3": 4, "A6": 38, "A7": 37, "A8": 32, "A9": 33, "D0": 3, "D1": 1, "D10": 5, "D11": 23, "D12": 19, "D13": 18, "D14": 12, "D15": 13, "D16": 15, "D17": 4, "D18": 22, "D19": 21, "D2": 16, "D20": 38, "D21": 37, "D3": 17, "D4": 32, "D5": 33, "D6": 25, "D7": 26, "D8": 27, "D9": 14, "SCL": 21, "SCL1": 13, "SDA": 22, "SDA1": 12, }, "nano32": {"BUTTON": 0, "LED": 16}, "nina_w10": { "D0": 3, "D1": 1, "D10": 5, "D11": 19, "D12": 23, "D13": 18, "D14": 13, "D15": 12, "D16": 32, "D17": 33, "D18": 21, "D19": 34, "D2": 26, "D20": 36, "D21": 39, "D3": 25, "D4": 35, "D5": 27, "D6": 22, "D7": 0, "D8": 15, "D9": 14, "LED_BLUE": 21, "LED_GREEN": 33, "LED_RED": 23, "SCL": 13, "SDA": 12, "SW1": 33, "SW2": 27, }, "node32s": {}, "nodemcu-32s": {"BUTTON": 0, "LED": 2}, "odroid_esp32": {"ADC1": 35, "ADC2": 36, "LED": 2, "SCL": 4, "SDA": 15, "SS": 22}, "onehorse32dev": {"A1": 37, "A2": 38, "BUTTON": 0, "LED": 5}, "oroca_edubot": { "A0": 34, "A1": 39, "A2": 36, "A3": 33, "D0": 4, "D1": 16, "D2": 17, "D3": 22, "D4": 23, "D5": 5, "D6": 18, "D7": 19, "D8": 33, "LED": 13, "MOSI": 18, "RX": 16, "SCK": 5, "SDA": 23, "SS": 2, "TX": 17, "VBAT": 35, }, "pico32": {}, "pocket_32": {"LED": 16}, "pycom_gpy": { "A1": 37, "A2": 38, "LED": 0, "MISO": 37, "MOSI": 22, "SCK": 13, "SCL": 13, "SDA": 12, "SS": 17, }, "quantum": {}, "sparkfun_lora_gateway_1-channel": {"MISO": 12, "MOSI": 13, "SCK": 14, "SS": 16}, "tinypico": {}, "ttgo-lora32-v1": { "A1": 37, "A2": 38, "BUTTON": 0, "LED": 2, "MOSI": 27, "SCK": 5, "SS": 18, }, "ttgo-t-beam": {"BUTTON": 39, "LED": 14, "MOSI": 27, "SCK": 5, "SS": 18}, "ttgo-t-watch": {"BUTTON": 36, "MISO": 2, "MOSI": 15, "SCK": 14, "SS": 13}, "ttgo-t1": {"LED": 22, "MISO": 2, "MOSI": 15, "SCK": 14, "SCL": 23, "SS": 13}, "ttgo-t7-v13-mini32": {"LED": 22}, "ttgo-t7-v14-mini32": {"LED": 19}, "turta_iot_node": {}, "vintlabs-devkit-v1": { "LED": 2, "PWM0": 12, "PWM1": 13, "PWM2": 14, "PWM3": 15, "PWM4": 16, "PWM5": 17, "PWM6": 18, "PWM7": 19, }, "wemos_d1_mini32": { "D0": 26, "D1": 22, "D2": 21, "D3": 17, "D4": 16, "D5": 18, "D6": 19, "D7": 23, "D8": 5, "LED": 2, "RXD": 3, "TXD": 1, "_VBAT": 35, }, "wemosbat": {"LED": 16}, "wesp32": {"MISO": 32, "SCL": 4, "SDA": 15}, "widora-air": { "A1": 39, "A2": 35, "A3": 25, "A4": 26, "A5": 14, "A6": 12, "A7": 15, "A8": 13, "A9": 2, "BUTTON": 0, "D0": 19, "D1": 23, "D2": 18, "D3": 17, "D4": 16, "D5": 5, "D6": 4, "LED": 25, "MISO": 17, "MOSI": 16, "SCL": 19, "SDA": 23, "T0": 19, "T1": 23, "T2": 18, "T3": 17, "T4": 16, "T5": 5, "T6": 4, }, "xinabox_cw02": {"LED": 27}, } def _lookup_pin(value): if CORE.is_esp8266: board_pins_dict = ESP8266_BOARD_PINS base_pins = ESP8266_BASE_PINS elif CORE.is_esp32: board_pins_dict = ESP32_BOARD_PINS base_pins = ESP32_BASE_PINS else: raise NotImplementedError board_pins = board_pins_dict.get(CORE.board, {}) # Resolved aliased board pins (shorthand when two boards have the same pin configuration) while isinstance(board_pins, str): board_pins = board_pins_dict[board_pins] if value in board_pins: return board_pins[value] if value in base_pins: return base_pins[value] raise cv.Invalid(f"Cannot resolve pin name '{value}' for board {CORE.board}.") def _translate_pin(value): if isinstance(value, dict) or value is None: raise cv.Invalid( "This variable only supports pin numbers, not full pin schemas " "(with inverted and mode)." ) if isinstance(value, int): return value try: return int(value) except ValueError: pass if value.startswith("GPIO"): return cv.Coerce(int)(value[len("GPIO") :].strip()) return _lookup_pin(value) _ESP_SDIO_PINS = { 6: "Flash Clock", 7: "Flash Data 0", 8: "Flash Data 1", 11: "Flash Command", } def validate_gpio_pin(value): value = _translate_pin(value) if CORE.is_esp32: if value < 0 or value > 39: raise cv.Invalid(f"ESP32: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: raise cv.Invalid( "This pin cannot be used on ESP32s and is already used by " "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) ) if 9 <= value <= 10: _LOGGER.warning( "ESP32: Pin %s (9-10) might already be used by the " "flash interface in QUAD IO flash mode.", value, ) if value in (20, 24, 28, 29, 30, 31): # These pins are not exposed in GPIO mux (reason unknown) # but they're missing from IO_MUX list in datasheet raise cv.Invalid(f"The pin GPIO{value} is not usable on ESP32s.") return value if CORE.is_esp8266: if value < 0 or value > 17: raise cv.Invalid(f"ESP8266: Invalid pin number: {value}") if value in _ESP_SDIO_PINS: raise cv.Invalid( "This pin cannot be used on ESP8266s and is already used by " "the flash interface (function: {})".format(_ESP_SDIO_PINS[value]) ) if 9 <= value <= 10: _LOGGER.warning( "ESP8266: Pin %s (9-10) might already be used by the " "flash interface in QUAD IO flash mode.", value, ) return value raise NotImplementedError def input_pin(value): value = validate_gpio_pin(value) if CORE.is_esp8266 and value == 17: raise cv.Invalid("GPIO17 (TOUT) is an analog-only pin on the ESP8266.") return value def input_pullup_pin(value): value = input_pin(value) if CORE.is_esp32: return output_pin(value) if CORE.is_esp8266: if value == 0: raise cv.Invalid( "GPIO Pin 0 does not support pullup pin mode. " "Please choose another pin." ) return value raise NotImplementedError def output_pin(value): value = validate_gpio_pin(value) if CORE.is_esp32: if 34 <= value <= 39: raise cv.Invalid( "ESP32: GPIO{} (34-39) can only be used as an " "input pin.".format(value) ) return value if CORE.is_esp8266: if value == 17: raise cv.Invalid("GPIO17 (TOUT) is an analog-only pin on the ESP8266.") return value raise NotImplementedError def analog_pin(value): value = validate_gpio_pin(value) if CORE.is_esp32: if 32 <= value <= 39: # ADC1 return value raise cv.Invalid("ESP32: Only pins 32 though 39 support ADC.") if CORE.is_esp8266: if value == 17: # A0 return value raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC.") raise NotImplementedError input_output_pin = cv.All(input_pin, output_pin) PIN_MODES_ESP8266 = [ "INPUT", "OUTPUT", "INPUT_PULLUP", "OUTPUT_OPEN_DRAIN", "SPECIAL", "FUNCTION_1", "FUNCTION_2", "FUNCTION_3", "FUNCTION_4", "FUNCTION_0", "WAKEUP_PULLUP", "WAKEUP_PULLDOWN", "INPUT_PULLDOWN_16", ] PIN_MODES_ESP32 = [ "INPUT", "OUTPUT", "INPUT_PULLUP", "OUTPUT_OPEN_DRAIN", "SPECIAL", "FUNCTION_1", "FUNCTION_2", "FUNCTION_3", "FUNCTION_4", "PULLUP", "PULLDOWN", "INPUT_PULLDOWN", "OPEN_DRAIN", "FUNCTION_5", "FUNCTION_6", "ANALOG", ] def pin_mode(value): if CORE.is_esp32: return cv.one_of(*PIN_MODES_ESP32, upper=True)(value) if CORE.is_esp8266: return cv.one_of(*PIN_MODES_ESP8266, upper=True)(value) raise NotImplementedError GPIO_FULL_OUTPUT_PIN_SCHEMA = cv.Schema( { cv.Required(CONF_NUMBER): output_pin, cv.Optional(CONF_MODE, default="OUTPUT"): pin_mode, cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) GPIO_FULL_INPUT_PIN_SCHEMA = cv.Schema( { cv.Required(CONF_NUMBER): input_pin, cv.Optional(CONF_MODE, default="INPUT"): pin_mode, cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) GPIO_FULL_INPUT_PULLUP_PIN_SCHEMA = cv.Schema( { cv.Required(CONF_NUMBER): input_pin, cv.Optional(CONF_MODE, default="INPUT_PULLUP"): pin_mode, cv.Optional(CONF_INVERTED, default=False): cv.boolean, } ) GPIO_FULL_ANALOG_PIN_SCHEMA = cv.Schema( { cv.Required(CONF_NUMBER): analog_pin, cv.Optional(CONF_MODE, default="INPUT"): pin_mode, } ) def shorthand_output_pin(value): value = output_pin(value) return GPIO_FULL_OUTPUT_PIN_SCHEMA({CONF_NUMBER: value}) def shorthand_input_pin(value): value = input_pin(value) return GPIO_FULL_INPUT_PIN_SCHEMA({CONF_NUMBER: value}) def shorthand_input_pullup_pin(value): value = input_pullup_pin(value) return GPIO_FULL_INPUT_PIN_SCHEMA( { CONF_NUMBER: value, CONF_MODE: "INPUT_PULLUP", } ) def shorthand_analog_pin(value): value = analog_pin(value) return GPIO_FULL_INPUT_PIN_SCHEMA({CONF_NUMBER: value}) def validate_has_interrupt(value): if CORE.is_esp8266: if value[CONF_NUMBER] >= 16: raise cv.Invalid( "Pins GPIO16 and GPIO17 do not support interrupts and cannot be used " "here, got {}".format(value[CONF_NUMBER]) ) return value PIN_SCHEMA_REGISTRY = SimpleRegistry() def internal_gpio_output_pin_schema(value): if isinstance(value, dict): return GPIO_FULL_OUTPUT_PIN_SCHEMA(value) return shorthand_output_pin(value) def gpio_output_pin_schema(value): if isinstance(value, dict): for key, entry in PIN_SCHEMA_REGISTRY.items(): if key in value: return entry[1][0](value) return internal_gpio_output_pin_schema(value) def internal_gpio_input_pin_schema(value): if isinstance(value, dict): return GPIO_FULL_INPUT_PIN_SCHEMA(value) return shorthand_input_pin(value) def internal_gpio_analog_pin_schema(value): if isinstance(value, dict): return GPIO_FULL_ANALOG_PIN_SCHEMA(value) return shorthand_analog_pin(value) def gpio_input_pin_schema(value): if isinstance(value, dict): for key, entry in PIN_SCHEMA_REGISTRY.items(): if key in value: return entry[1][1](value) return internal_gpio_input_pin_schema(value) def internal_gpio_input_pullup_pin_schema(value): if isinstance(value, dict): return GPIO_FULL_INPUT_PULLUP_PIN_SCHEMA(value) return shorthand_input_pullup_pin(value) def gpio_input_pullup_pin_schema(value): if isinstance(value, dict): for key, entry in PIN_SCHEMA_REGISTRY.items(): if key in value: return entry[1][1](value) return internal_gpio_input_pullup_pin_schema(value)