import esphome.codegen as cg import esphome.config_validation as cv from esphome import automation from esphome.components import output, sensor from esphome.const import ( CONF_ID, CONF_TRIGGER_ID ) DEPENDENCIES=["sensor"] chlorine_pump_ns = cg.esphome_ns.namespace('chlorine_pump') ChlorinePump = chlorine_pump_ns.class_('ChlorinePump', cg.Component) CONF_SENSOR = "sensor" CONF_PUMP_OUT = "pump" CONF_PUMP_CYCLE_TIME = "cycle_time" CONF_PUMP_PROPORTIONAL_BAND = "proportional_band" CONF_PUMP_VALUE = "on_pump_value" CONF_CYCLE_START = "on_cycle_start" CONF_DISABLE_CLOCK="disable_clock" CONF_TARGET="target" CONF_TARGET_LAMBDA="get_target" CONF_PUMP_TIME_DIVIDER = "pump_time_divider" def to_proportional_band(value): try: value = int(value) except (TypeError, ValueError): # pylint: disable=raise-missing-from raise cv.Invalid(f"") return cv.one_of(20, 50, 100, 150, 200, 300, 400)(value) ChlorSensorOutputTrigger = chlorine_pump_ns.class_( "ChlorSensorOutputTrigger", automation.Trigger.template(cg.bool_, cg.int_) ) ChlorSensorCycleTrigger = chlorine_pump_ns.class_( "ChlorSensorCycleTrigger", automation.Trigger.template(cg.int_, cg.int_) ) PrimeAction = chlorine_pump_ns.class_("ChlorinePrime", automation.Action) StartAction = chlorine_pump_ns.class_("ChlorineStart", automation.Action) StopAction = chlorine_pump_ns.class_("ChlorineStop", automation.Action) SetTargetAction = chlorine_pump_ns.class_("ChlorineSetTarget", automation.Action) ManualDoseAction = chlorine_pump_ns.class_("ChlorineDose", automation.Action) def validate_config(config): if (config.get(CONF_TARGET_LAMBDA, None) is not None) is not (config.get(CONF_TARGET, None) not in config): raise cv.Invalid("Either a fixed target or an get_target lambda must be set to get a target") return config CONFIG_SCHEMA = cv.All( cv.COMPONENT_SCHEMA.extend({ cv.GenerateID(): cv.declare_id(ChlorinePump), cv.Required(CONF_PUMP_OUT): cv.use_id(output.BinaryOutput), cv.Optional(CONF_SENSOR): cv.use_id(sensor.Sensor), cv.Optional(CONF_PUMP_CYCLE_TIME, default=360): cv.int_range(min=30, max=1400), cv.Optional(CONF_PUMP_PROPORTIONAL_BAND, default=200): to_proportional_band, cv.Optional(CONF_DISABLE_CLOCK, default=False): cv.boolean, cv.Optional(CONF_TARGET): cv.int_range(300, 1400), cv.Optional(CONF_PUMP_TIME_DIVIDER, 2): cv.float_range(1, 5), cv.Optional(CONF_TARGET_LAMBDA, 2): cv.templatable(cv.float_), cv.Optional(CONF_PUMP_VALUE): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorOutputTrigger), } ), cv.Optional(CONF_CYCLE_START): automation.validate_automation({ cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ChlorSensorCycleTrigger), } ), }), validate_config ) ACTION_SCHEMA = cv.Schema({ cv.GenerateID(): cv.use_id(ChlorinePump) }) @automation.register_action("chlorine_pump.prime", PrimeAction, ACTION_SCHEMA) async def prime_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action("chlorine_pump.start", StartAction, ACTION_SCHEMA) async def start_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action("chlorine_pump.stop", StopAction, ACTION_SCHEMA) async def stop_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action("chlorine_pump.manual_dose", StopAction, ACTION_SCHEMA) async def stop_action_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) return cg.new_Pvariable(action_id, template_arg, paren) @automation.register_action("chlorine_pump.set_target", SetTargetAction, ACTION_SCHEMA.extend({ cv.Required(CONF_TARGET): cv.templatable(cv.float_), })) async def number_set_to_code(config, action_id, template_arg, args): paren = await cg.get_variable(config[CONF_ID]) var = cg.new_Pvariable(action_id, template_arg, paren) template_ = await cg.templatable(config[CONF_TARGET], args, float) cg.add(var.set_value(template_)) return var async def to_code(config): var = cg.new_Pvariable(config[CONF_ID]) await cg.register_component(var, config) #yield mqtt.register_mqtt_component(var, config) #btnReset = yield cg.gpio_pin_expression(config[CONF_SENSOR_PIN]) #cg.add(var.set_input_pin(btnReset)) if CONF_SENSOR in config: sensor = await cg.get_variable(config[CONF_SENSOR]) cg.add(var.set_sensor(sensor)) pump_out = await cg.get_variable(config[CONF_PUMP_OUT]) cg.add(var.set_pump_out(pump_out)) cg.add(var.set_cycle_time(config[CONF_PUMP_CYCLE_TIME])) # Needs be configured before sensor cg.add(var.disable_clock(config[CONF_DISABLE_CLOCK])) #cycle_time = yield cg.get_variable(config[CONF_PUMP_CYCLE_TIME]) #prop_band = yield cg.get_variable(config[CONF_PUMP_PROPORTIONAL_BAND]) cg.add(var.set_prop_band(config[CONF_PUMP_PROPORTIONAL_BAND])) #cg.add(var.set_state(config[CONF_STATE])) if CONF_TARGET not in config: template_ = await cg.templatable(config[CONF_TARGET_LAMBDA], [], float) cg.add(var.set_target_lambda(template_)) else: cg.add(var.set_target(config[CONF_TARGET])) if CONF_PUMP_VALUE in config: for conf in config.get(CONF_PUMP_VALUE, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(bool, "pState"), (int, "pTime")], conf) for conf in config.get(CONF_CYCLE_START, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [(int, "tOn"), (int, "tOff")], conf)