All the code changes to the chlorine pump... More will follow
This commit is contained in:
parent
a96531dda9
commit
3d7e80154a
141
chlorPump.yaml
141
chlorPump.yaml
@ -3,6 +3,10 @@ esphome:
|
||||
project:
|
||||
name: nbsgamesat.chlorine-pump
|
||||
version: "0.2"
|
||||
on_boot:
|
||||
priority: 600
|
||||
then:
|
||||
output.turn_on: whatever
|
||||
|
||||
esp8266:
|
||||
board: nodemcuv2
|
||||
@ -17,7 +21,15 @@ external_components:
|
||||
- source:
|
||||
type: local
|
||||
path: external_components/
|
||||
components: [ analog_orp ]
|
||||
components: [ analog_orp, chlorine_pump ]
|
||||
|
||||
globals:
|
||||
- id: last_pump_state
|
||||
type: bool
|
||||
restore_value: no
|
||||
initial_value: "false"
|
||||
- id: last_cycle_info
|
||||
type: std::string
|
||||
|
||||
api:
|
||||
encryption:
|
||||
@ -27,31 +39,144 @@ wifi:
|
||||
ssid: !secret wifi_ssid
|
||||
password: !secret wifi_password
|
||||
fast_connect: true
|
||||
on_connect:
|
||||
output.turn_off: whatever
|
||||
|
||||
output:
|
||||
- platform: gpio
|
||||
pin: D3
|
||||
pin: D6
|
||||
id: pump_switch
|
||||
- platform: gpio
|
||||
pin:
|
||||
number: D0
|
||||
inverted: true
|
||||
id: whatever
|
||||
|
||||
binary_sensor:
|
||||
- platform: gpio
|
||||
id: pool_pump
|
||||
pin: D2
|
||||
pin:
|
||||
number: D2
|
||||
inverted: true
|
||||
mode:
|
||||
input: true
|
||||
pullup: true
|
||||
on_state:
|
||||
- script.execute:
|
||||
id: manage_power
|
||||
switch_state: !lambda return id(power).state;
|
||||
- platform: template
|
||||
id: pump_state
|
||||
name: Pump State
|
||||
lambda: !lambda return id(last_pump_state);
|
||||
|
||||
script:
|
||||
- id: manage_power
|
||||
parameters:
|
||||
switch_state: bool
|
||||
then:
|
||||
- if:
|
||||
condition:
|
||||
lambda: |-
|
||||
return switch_state && id(pool_pump).state;
|
||||
then:
|
||||
- chlorine_pump.start: {}
|
||||
- text_sensor.template.publish:
|
||||
id: cycle_text_info
|
||||
state: !lambda 'return "ON... ";'
|
||||
else:
|
||||
- chlorine_pump.stop: {}
|
||||
- text_sensor.template.publish:
|
||||
id: cycle_text_info
|
||||
state: !lambda 'return "PUMP: OFF";'
|
||||
|
||||
switch:
|
||||
- platform: template
|
||||
name: Chlorine Pump Power
|
||||
id: power
|
||||
optimistic: true
|
||||
inverted: off
|
||||
restore_mode: RESTORE_DEFAULT_ON
|
||||
turn_on_action:
|
||||
- script.execute:
|
||||
id: manage_power
|
||||
switch_state: true
|
||||
turn_off_action:
|
||||
- script.execute:
|
||||
id: manage_power
|
||||
switch_state: false
|
||||
|
||||
button:
|
||||
- platform: template
|
||||
name: Prime
|
||||
id: prime
|
||||
on_press:
|
||||
- chlorine_pump.prime: {}
|
||||
- text_sensor.template.publish:
|
||||
id: cycle_text_info
|
||||
state: !lambda 'return "PRIMING??";'
|
||||
|
||||
number:
|
||||
- platform: template
|
||||
name: Chlorine Target
|
||||
id: chlorine_target
|
||||
initial_value: 700
|
||||
restore_value: true
|
||||
min_value: 300
|
||||
max_value: 1400
|
||||
optimistic: true
|
||||
step: 1.0
|
||||
set_action:
|
||||
then:
|
||||
- chlorine_pump.set_target:
|
||||
target: !lambda return x;
|
||||
|
||||
text_sensor:
|
||||
- platform: template
|
||||
name: Cycle Info
|
||||
id: cycle_text_info
|
||||
|
||||
sensor:
|
||||
- platform: analog_orp
|
||||
name: Chlorine
|
||||
id: chlorine_sensor
|
||||
pin: A0
|
||||
zero_point: 640
|
||||
zero_point: 673
|
||||
inverted: true
|
||||
update_interval: 1s
|
||||
# print_raw: true
|
||||
average:
|
||||
mesurements: 5
|
||||
mesurements: 15
|
||||
send_state_every: 10
|
||||
on_completely_new_value:
|
||||
# on_value_read:
|
||||
# - lambda: |-
|
||||
# ESP_LOGD("WHAT", "Chlorine_value, %.1f", x);
|
||||
- platform: hx711
|
||||
name: "Chlorine Canister Levels"
|
||||
dout_pin: D5
|
||||
clk_pin: D1
|
||||
gain: 128
|
||||
update_interval: 20s
|
||||
accuracy_decimals: 1
|
||||
filters:
|
||||
- calibrate_linear:
|
||||
- 47608 -> 0
|
||||
- 590566 -> 100
|
||||
unit_of_measurement: "%"
|
||||
|
||||
chlorine_pump:
|
||||
pump: pump_switch
|
||||
sensor: chlorine_sensor
|
||||
id: chlorine_pump_component
|
||||
target: 700
|
||||
disable_clock: true
|
||||
on_pump_value:
|
||||
- lambda: |-
|
||||
ESP_LOGD("WHAT", "Just a test %.1f", value);
|
||||
# GPIO A0 to acd
|
||||
if(pState != id(last_pump_state)){
|
||||
id(last_pump_state) = pState;
|
||||
}
|
||||
on_cycle_start:
|
||||
- lambda: |-
|
||||
id(cycle_text_info).publish_state("tOn: " + std::to_string(tOn) + "s\n tOff: " + std::to_string(tOff) + "s");
|
||||
|
||||
# Here is space for any display implementation that could possibliy be. Have fun OK
|
@ -0,0 +1 @@
|
||||
CODEOWNERS = ["@nbsgames"]
|
@ -109,6 +109,9 @@ void ChlorineSensor::dump_config(){
|
||||
ESP_LOGCONFIG(TAG, " Inverted: %s", inverted_ ? "true" : "false");
|
||||
ESP_LOGCONFIG(TAG, " Print Raw: %s", print_raw_ ? "true" : "false");
|
||||
}
|
||||
bool ChlorineSensor::has_averager(){
|
||||
return averager_ != nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
Nullwert : 680
|
||||
|
@ -1,10 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome.h"
|
||||
#include "esphome/components/sensor/sensor.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/gpio.h"
|
||||
#include "esphome/core/automation.h"
|
||||
#include "Arduino.h"
|
||||
|
||||
namespace esphome {
|
||||
namespace analog_orp {
|
||||
@ -33,6 +33,7 @@ class ChlorineSensor: public PollingComponent, public sensor::Sensor {
|
||||
void add_average_change_callback(std::function<void(float)> &&callback);
|
||||
void add_new_value_callback(std::function<void(float)> &&callback);
|
||||
void init_averager(int mesurements, int send_average_every);
|
||||
bool has_averager();
|
||||
void setup() override;
|
||||
void update() override;
|
||||
float sample();
|
||||
|
@ -26,7 +26,7 @@ CONF_AVERAGE_NEW = "on_completely_new_value"
|
||||
|
||||
UNIT_MILLI_VOLT = "mV"
|
||||
|
||||
ICON_LIGHTNING_BOLT="mdi:lightning-bolt"
|
||||
ICON_TEST_TUBE="mdi:test-tube"
|
||||
|
||||
ChlorineValueRead = chlorine_sensor_ns.class_(
|
||||
"ChlorineValueReadTrigger", automation.Trigger.template(cg.float_)
|
||||
@ -45,7 +45,7 @@ CONFIG_SCHEMA = cv.All(
|
||||
accuracy_decimals=2,
|
||||
device_class=DEVICE_CLASS_VOLTAGE,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
icon=ICON_LIGHTNING_BOLT
|
||||
icon=ICON_TEST_TUBE
|
||||
).extend({
|
||||
cv.Required(CONF_SENSOR_PIN): adc.validate_adc_pin,
|
||||
cv.Required(CONF_ZERO_POINT): cv.Range(min=0, max=1023),
|
||||
@ -88,12 +88,12 @@ async def to_code(config):
|
||||
|
||||
for conf in averager_config.get(CONF_ON_READ_VALUE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
||||
await automation.build_automation(trigger, [(float, "x")], conf)
|
||||
|
||||
for conf in averager_config.get(CONF_AVERAGE_ON_VALUE, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
||||
await automation.build_automation(trigger, [(float, "x")], conf)
|
||||
|
||||
for conf in averager_config.get(CONF_AVERAGE_NEW, []):
|
||||
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
|
||||
await automation.build_automation(trigger, [(float, "value")], conf)
|
||||
await automation.build_automation(trigger, [(float, "x")], conf)
|
128
external_components/chlorine_pump/__init__.py
Normal file
128
external_components/chlorine_pump/__init__.py
Normal file
@ -0,0 +1,128 @@
|
||||
import esphome.codegen as cg
|
||||
import esphome.config_validation as cv
|
||||
from esphome import automation
|
||||
from esphome.components import output
|
||||
from esphome.components.analog_orp.sensor import ChlorineSensor
|
||||
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"
|
||||
|
||||
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, 250)(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)
|
||||
|
||||
CONFIG_SCHEMA = 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(ChlorineSensor),
|
||||
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, 700): cv.int_range(300, 1400),
|
||||
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),
|
||||
}
|
||||
),
|
||||
})
|
||||
|
||||
|
||||
|
||||
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.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))
|
||||
|
||||
|
||||
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_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)
|
216
external_components/chlorine_pump/pump_cycle.h
Normal file
216
external_components/chlorine_pump/pump_cycle.h
Normal file
@ -0,0 +1,216 @@
|
||||
#pragma once
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/components/gpio/output/gpio_binary_output.h"
|
||||
#include "esphome/components/analog_orp/analog_orp.h"
|
||||
|
||||
static const char *const TAG = "chlorine_pump";
|
||||
|
||||
namespace esphome {
|
||||
namespace chlorine_pump {
|
||||
|
||||
class ChlorinePump : public Component {
|
||||
protected:
|
||||
|
||||
analog_orp::ChlorineSensor *sensor_;
|
||||
gpio::GPIOBinaryOutput *pump_out;
|
||||
int cycle_time;
|
||||
int prop_band;
|
||||
bool state = true;
|
||||
unsigned long last_action;
|
||||
bool disable_clock_ = false;
|
||||
CallbackManager<void(bool, int)> callback_pump_;
|
||||
CallbackManager<void(int, int)> callback_cycle_;
|
||||
int tOn = 0;
|
||||
int tOff = 0;
|
||||
float target_ = 700.0f;
|
||||
|
||||
public:
|
||||
|
||||
ChlorinePump(){
|
||||
last_action = 0;
|
||||
}
|
||||
|
||||
|
||||
void disable_clock(bool disable_clock){
|
||||
this->disable_clock_ = disable_clock;
|
||||
}
|
||||
void set_sensor(analog_orp::ChlorineSensor *sensor){
|
||||
this->sensor_ = sensor;
|
||||
}
|
||||
void set_pump_out(gpio::GPIOBinaryOutput *pump_out){
|
||||
this->pump_out = pump_out;
|
||||
}
|
||||
void set_cycle_time(int time_in_sec){
|
||||
this->cycle_time = time_in_sec;
|
||||
}
|
||||
void set_prop_band(int prop_band){
|
||||
this->prop_band = prop_band;
|
||||
}
|
||||
void set_target(int target){
|
||||
this->target_ = (float) target;
|
||||
}
|
||||
|
||||
void setup() override {
|
||||
last_action = millis();
|
||||
if(disable_clock_ && sensor_ != nullptr){
|
||||
if(!sensor_->has_averager()) sensor_->add_on_state_callback([=](float val) -> void {
|
||||
this->tick_time(val);
|
||||
});
|
||||
if(sensor_->has_averager()) sensor_->add_average_change_callback([=](float val) -> void {
|
||||
this->tick_time(val);
|
||||
});
|
||||
}
|
||||
}
|
||||
void prime() {
|
||||
tOn = 30;
|
||||
tOff = 2;
|
||||
this->pump_out->turn_on();
|
||||
}
|
||||
void start() {
|
||||
this->state = true;
|
||||
}
|
||||
void stop() {
|
||||
this->state = false;
|
||||
tOn = 0;
|
||||
tOff = 0;
|
||||
this->pump_out->turn_off();
|
||||
}
|
||||
bool get_state(){
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void setMillisPrecies(unsigned long waitPeriod){
|
||||
|
||||
if(last_action + waitPeriod + waitPeriod > millis()){
|
||||
last_action += waitPeriod;
|
||||
}
|
||||
else{
|
||||
ESP_LOGW(TAG, "Reset millis(). Did the system experience a halt for some reason?");
|
||||
last_action = millis();
|
||||
}
|
||||
}
|
||||
|
||||
int calculatePumpTimeSeconds(float last_mesurement){
|
||||
|
||||
if(last_mesurement >= target_) return 0;
|
||||
|
||||
float currentVal = target_ - last_mesurement;
|
||||
float proportionalValue = (currentVal / (float) prop_band);
|
||||
float timeInSeconds = proportionalValue * (float) cycle_time;
|
||||
|
||||
if(timeInSeconds > cycle_time) timeInSeconds = cycle_time;
|
||||
|
||||
return (int) timeInSeconds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_on_pump_callback(std::function<void(bool, int)> &&callback){
|
||||
this->callback_pump_.add(std::move(callback));
|
||||
}
|
||||
void add_on_cycle_callback(std::function<void(int, int)> &&callback){
|
||||
this->callback_cycle_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void tick_time(float last_mesurement){
|
||||
|
||||
if(tOn == 0 && tOff == 0 && state){
|
||||
int seconds = calculatePumpTimeSeconds(last_mesurement);
|
||||
|
||||
if(seconds == 0){
|
||||
tOn = 0;
|
||||
tOff = 30;
|
||||
}
|
||||
|
||||
tOn = seconds;
|
||||
tOff = cycle_time - tOn;
|
||||
|
||||
ESP_LOGD(TAG, "Time => tOn: %d, tOff: %d", tOn, tOff);
|
||||
|
||||
this->callback_cycle_.call(tOn, tOff);
|
||||
}
|
||||
else if(tOn > 0) {
|
||||
this->callback_pump_.call(true, tOn);
|
||||
--tOn;
|
||||
pump_out->turn_on();
|
||||
}
|
||||
else if(tOff > 0) {
|
||||
this->callback_pump_.call(false, tOff);
|
||||
--tOff;
|
||||
pump_out->turn_off();
|
||||
}
|
||||
}
|
||||
|
||||
void loop() override{
|
||||
|
||||
if(disable_clock_) return;
|
||||
|
||||
if(millis() - last_action > 1000){
|
||||
|
||||
tick_time(sensor_->get_state());
|
||||
|
||||
setMillisPrecies(1000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ChlorSensorOutputTrigger : public Trigger<bool, int> {
|
||||
public:
|
||||
explicit ChlorSensorOutputTrigger(ChlorinePump *parent) {
|
||||
parent->add_on_pump_callback([this](bool output_state, int value) { this->trigger(output_state, value); });
|
||||
}
|
||||
};
|
||||
class ChlorSensorCycleTrigger : public Trigger<int, int> {
|
||||
public:
|
||||
explicit ChlorSensorCycleTrigger(ChlorinePump *parent) {
|
||||
parent->add_on_cycle_callback([this](int on_time, int off_time) { this->trigger(on_time, off_time); });
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... Ts> class ChlorinePrime : public Action<Ts...> {
|
||||
public:
|
||||
ChlorinePrime(ChlorinePump *pump) : pump_(pump) {}
|
||||
|
||||
void play(Ts... x) override { this->pump_->prime(); }
|
||||
|
||||
protected:
|
||||
ChlorinePump *pump_;
|
||||
};
|
||||
template<typename... Ts> class ChlorineStart : public Action<Ts...> {
|
||||
public:
|
||||
ChlorineStart(ChlorinePump *pump) : pump_(pump) {}
|
||||
|
||||
void play(Ts... x) override { this->pump_->start(); }
|
||||
|
||||
protected:
|
||||
ChlorinePump *pump_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ChlorineStop : public Action<Ts...> {
|
||||
public:
|
||||
ChlorineStop(ChlorinePump *pump) : pump_(pump) {}
|
||||
|
||||
void play(Ts... x) override { this->pump_->stop(); }
|
||||
|
||||
protected:
|
||||
ChlorinePump *pump_;
|
||||
};
|
||||
|
||||
template<typename... Ts> class ChlorineSetTarget : public Action<Ts...> {
|
||||
public:
|
||||
ChlorineSetTarget(ChlorinePump *pump) : pump_(pump) {}
|
||||
TEMPLATABLE_VALUE(float, value)
|
||||
|
||||
void play(Ts... x) override {
|
||||
this->pump_->set_target((int) this->value_.value(x...));
|
||||
}
|
||||
|
||||
protected:
|
||||
ChlorinePump *pump_;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user