From 5263c13bb23b3be8a6564444c5796347f7475b33 Mon Sep 17 00:00:00 2001 From: Lazar Obradovic Date: Mon, 15 Oct 2018 21:09:37 +0200 Subject: [PATCH] MCP23017 support. --- esphomeyaml/components/mcp23017.py | 26 ++++++++++++++++++++++++++ esphomeyaml/const.py | 1 + esphomeyaml/helpers.py | 14 ++++++++++---- esphomeyaml/pins.py | 17 ++++++++++++++++- tests/test1.yaml | 20 ++++++++++++++++++++ 5 files changed, 73 insertions(+), 5 deletions(-) create mode 100644 esphomeyaml/components/mcp23017.py diff --git a/esphomeyaml/components/mcp23017.py b/esphomeyaml/components/mcp23017.py new file mode 100644 index 0000000000..985999e3e6 --- /dev/null +++ b/esphomeyaml/components/mcp23017.py @@ -0,0 +1,26 @@ +import voluptuous as vol + +import esphomeyaml.config_validation as cv +from esphomeyaml.const import CONF_ADDRESS, CONF_ID, CONF_MCP23017 +from esphomeyaml.helpers import App, Pvariable, esphomelib_ns + +DEPENDENCIES = ['i2c'] + +io_ns = esphomelib_ns.namespace('io') +MCP23017Component = io_ns.MCP23017Component + +MCP23017_SCHEMA = vol.Schema({ + vol.Required(CONF_ID): cv.declare_variable_id(MCP23017Component), + vol.Optional(CONF_ADDRESS, default=0x20): cv.i2c_address, +}) + +CONFIG_SCHEMA = vol.All(cv.ensure_list, [MCP23017_SCHEMA]) + + +def to_code(config): + for conf in config: + rhs = App.make_mcp23017_component(conf[CONF_ADDRESS]) + Pvariable(conf[CONF_ID], rhs) + + +BUILD_FLAGS = '-DUSE_MCP23017' diff --git a/esphomeyaml/const.py b/esphomeyaml/const.py index 987e27217f..7ec4d72dee 100644 --- a/esphomeyaml/const.py +++ b/esphomeyaml/const.py @@ -194,6 +194,7 @@ CONF_JS_URL = 'js_url' CONF_SSL_FINGERPRINTS = 'ssl_fingerprints' CONF_PCF8574 = 'pcf8574' CONF_PCF8575 = 'pcf8575' +CONF_MCP23017 = 'mcp23017' CONF_SCAN = 'scan' CONF_KEEPALIVE = 'keepalive' CONF_INTEGRATION_TIME = 'integration_time' diff --git a/esphomeyaml/helpers.py b/esphomeyaml/helpers.py index 601205aa87..9aaf31826d 100644 --- a/esphomeyaml/helpers.py +++ b/esphomeyaml/helpers.py @@ -10,7 +10,7 @@ from esphomeyaml import core from esphomeyaml.const import CONF_AVAILABILITY, CONF_COMMAND_TOPIC, CONF_DISCOVERY, \ CONF_INVERTED, \ CONF_MODE, CONF_NUMBER, CONF_PAYLOAD_AVAILABLE, CONF_PAYLOAD_NOT_AVAILABLE, CONF_PCF8574, \ - CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC + CONF_MCP23017, CONF_RETAIN, CONF_STATE_TOPIC, CONF_TOPIC from esphomeyaml.core import ESPHomeYAMLError, HexInt, Lambda, TimePeriodMicroseconds, \ TimePeriodMilliseconds, TimePeriodSeconds @@ -585,15 +585,21 @@ def generic_gpio_pin_expression_(conf, mock_obj, default_mode): return number = conf[CONF_NUMBER] inverted = conf.get(CONF_INVERTED) - if CONF_PCF8574 in conf: + if any (mux in conf for mux in [CONF_PCF8574, CONF_MCP23017]): hub = None - for hub in get_variable(conf[CONF_PCF8574]): + for hub in get_variable(conf[mux]): yield None if default_mode == u'INPUT': mode = conf.get(CONF_MODE, u'INPUT') - yield hub.make_input_pin(number, + if mux == CONF_PCF8574: + yield hub.make_input_pin(number, RawExpression('PCF8574_' + mode), inverted) + elif mux == CONF_MCP23017: + yield hub.make_input_pin(number, + RawExpression('MCP23017_' + mode), + inverted) + return elif default_mode == u'OUTPUT': yield hub.make_output_pin(number, inverted) diff --git a/esphomeyaml/pins.py b/esphomeyaml/pins.py index 1b67860ed4..31820770b4 100644 --- a/esphomeyaml/pins.py +++ b/esphomeyaml/pins.py @@ -5,8 +5,9 @@ import voluptuous as vol import esphomeyaml.config_validation as cv from esphomeyaml import core from esphomeyaml.components import pcf8574 +from esphomeyaml.components import mcp23017 from esphomeyaml.const import CONF_INVERTED, CONF_MODE, CONF_NUMBER, CONF_PCF8574, \ - ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 + CONF_MCP23017, ESP_PLATFORM_ESP32, ESP_PLATFORM_ESP8266 _LOGGER = logging.getLogger(__name__) @@ -296,6 +297,16 @@ PCF8574_INPUT_PIN_SCHEMA = PCF8574_OUTPUT_PIN_SCHEMA.extend({ vol.Optional(CONF_MODE): vol.All(vol.Upper, cv.one_of("INPUT", "INPUT_PULLUP")), }) +MCP23017_OUTPUT_PIN_SCHEMA = vol.Schema({ + vol.Required(CONF_MCP23017): cv.use_variable_id(mcp23017.MCP23017Component), + vol.Required(CONF_NUMBER): vol.Coerce(int), + vol.Optional(CONF_MODE): vol.All(vol.Upper, cv.one_of("OUTPUT")), + vol.Optional(CONF_INVERTED, default=False): cv.boolean, +}) + +MCP23017_INPUT_PIN_SCHEMA = MCP23017_OUTPUT_PIN_SCHEMA.extend({ + vol.Optional(CONF_MODE): vol.All(vol.Upper, cv.one_of("INPUT", "INPUT_PULLUP")), +}) def internal_gpio_output_pin_schema(value): if isinstance(value, dict): @@ -307,6 +318,8 @@ def gpio_output_pin_schema(value): if isinstance(value, dict): if CONF_PCF8574 in value: return PCF8574_OUTPUT_PIN_SCHEMA(value) + if CONF_MCP23017 in value: + return MCP23017_OUTPUT_PIN_SCHEMA(value) return GPIO_FULL_OUTPUT_PIN_SCHEMA(value) return shorthand_output_pin(value) @@ -321,5 +334,7 @@ def gpio_input_pin_schema(value): if isinstance(value, dict): if CONF_PCF8574 in value: return PCF8574_INPUT_PIN_SCHEMA(value) + if CONF_MCP23017 in value: + return MCP23017_INPUT_PIN_SCHEMA(value) return GPIO_FULL_INPUT_PIN_SCHEMA(value) return shorthand_input_pin(value) diff --git a/tests/test1.yaml b/tests/test1.yaml index 626f660c19..d9906794e2 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -510,6 +510,13 @@ binary_sensor: number: 1 mode: INPUT inverted: True + - platform: gpio + name: "MCP binary sensor" + pin: + mcp23017: mcp23017_hub + number: 2 + mode: INPUT + inverted: False pca9685: frequency: 500 @@ -559,6 +566,15 @@ output: number: 0 mode: OUTPUT inverted: False + - platform: gpio + id: id20 + pin: + mcp23017: mcp23017_hub + number: 0 + mode: OUTPUT + inverted: False + + light: - platform: binary @@ -901,3 +917,7 @@ pcf8574: - id: 'pcf8574_hub' address: 0x21 pcf8575: False + +mcp23017: + - id: 'mcp23017_hub' + address: 0x20