diff --git a/esphome/components/rotary_encoder/rotary_encoder.h b/esphome/components/rotary_encoder/rotary_encoder.h index b627a4e57f..4220645478 100644 --- a/esphome/components/rotary_encoder/rotary_encoder.h +++ b/esphome/components/rotary_encoder/rotary_encoder.h @@ -2,6 +2,7 @@ #include "esphome/core/component.h" #include "esphome/core/esphal.h" +#include "esphome/core/automation.h" #include "esphome/components/sensor/sensor.h" namespace esphome { @@ -43,6 +44,12 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { */ void set_resolution(RotaryEncoderResolution mode); + /// Manually set the value of the counter. + void set_value(int value) { + this->store_.counter = value; + this->loop(); + } + void set_reset_pin(GPIOPin *pin_i) { this->pin_i_ = pin_i; } void set_min_value(int32_t min_value); void set_max_value(int32_t max_value); @@ -63,5 +70,15 @@ class RotaryEncoderSensor : public sensor::Sensor, public Component { RotaryEncoderSensorStore store_{}; }; +template class RotaryEncoderSetValueAction : public Action { + public: + RotaryEncoderSetValueAction(RotaryEncoderSensor *encoder) : encoder_(encoder) {} + TEMPLATABLE_VALUE(int, value) + void play(Ts... x) override { this->encoder_->set_value(this->value_.value(x...)); } + + protected: + RotaryEncoderSensor *encoder_; +}; + } // namespace rotary_encoder } // namespace esphome diff --git a/esphome/components/rotary_encoder/sensor.py b/esphome/components/rotary_encoder/sensor.py index fb4881e18b..742096cd5a 100644 --- a/esphome/components/rotary_encoder/sensor.py +++ b/esphome/components/rotary_encoder/sensor.py @@ -1,9 +1,9 @@ import esphome.codegen as cg import esphome.config_validation as cv -from esphome import pins +from esphome import pins, automation from esphome.components import sensor from esphome.const import CONF_ID, CONF_RESOLUTION, CONF_MIN_VALUE, CONF_MAX_VALUE, UNIT_STEPS, \ - ICON_ROTATE_RIGHT + ICON_ROTATE_RIGHT, CONF_VALUE rotary_encoder_ns = cg.esphome_ns.namespace('rotary_encoder') RotaryEncoderResolution = rotary_encoder_ns.enum('RotaryEncoderResolution') @@ -18,6 +18,8 @@ CONF_PIN_B = 'pin_b' CONF_PIN_RESET = 'pin_reset' RotaryEncoderSensor = rotary_encoder_ns.class_('RotaryEncoderSensor', sensor.Sensor, cg.Component) +RotaryEncoderSetValueAction = rotary_encoder_ns.class_('RotaryEncoderSetValueAction', + automation.Action) def validate_min_max_value(config): @@ -60,3 +62,16 @@ def to_code(config): cg.add(var.set_min_value(config[CONF_MIN_VALUE])) if CONF_MAX_VALUE in config: cg.add(var.set_max_value(config[CONF_MAX_VALUE])) + + +@automation.register_action('sensor.rotary_encoder.set_value', RotaryEncoderSetValueAction, + cv.Schema({ + cv.Required(CONF_ID): cv.use_id(sensor.Sensor), + cv.Required(CONF_VALUE): cv.templatable(cv.int_), + })) +def sensor_template_publish_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_VALUE], args, int) + cg.add(var.set_value(template_)) + yield var diff --git a/tests/test1.yaml b/tests/test1.yaml index f2adaa19fd..f35b9caf2f 100644 --- a/tests/test1.yaml +++ b/tests/test1.yaml @@ -491,6 +491,7 @@ sensor: update_interval: 15s - platform: rotary_encoder name: "Rotary Encoder" + id: rotary_encoder1 pin_a: GPIO23 pin_b: GPIO24 pin_reset: GPIO25 @@ -501,6 +502,13 @@ sensor: resolution: 4 min_value: -10 max_value: 30 + on_value: + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: 10 + - sensor.rotary_encoder.set_value: + id: rotary_encoder1 + value: !lambda 'return -1;' - platform: pulse_width name: Pulse Width pin: GPIO12