Compare commits

...
6 changed files with 72 additions and 72 deletions

No files matched your search

@@ -12,7 +12,7 @@ void PipsolarOutput::write_state(float state) {
if (std::find(this->possible_values_.begin(), this->possible_values_.end(), state) != this->possible_values_.end()) {
ESP_LOGD(TAG, "Will write: %s out of value %f / %02.0f", tmp, state, state);
this->parent_->queue_command(std::string(tmp));
this->parent_->queue_command(tmp);
} else {
ESP_LOGD(TAG, "Will not write: %s as it is not in list of allowed values", tmp);
}
+9 -3
View File
@@ -224,17 +224,23 @@ bool Pipsolar::send_next_poll_() {
return false;
}
void Pipsolar::queue_command(const std::string &command) {
void Pipsolar::write_switch(bool state, const char *on, const char *off) {
const char *command = state ? on : off;
if (command != nullptr)
this->queue_command(command);
}
void Pipsolar::queue_command(const char *command) {
uint8_t next_position = command_queue_position_;
for (uint8_t i = 0; i < COMMAND_QUEUE_LENGTH; i++) {
uint8_t testposition = (next_position + i) % COMMAND_QUEUE_LENGTH;
if (command_queue_[testposition].empty()) {
command_queue_[testposition] = command;
ESP_LOGD(TAG, "Command queued successfully: %s at position %d", command.c_str(), testposition);
ESP_LOGD(TAG, "Command queued successfully: %s at position %d", command, testposition);
return;
}
}
ESP_LOGD(TAG, "Command queue full dropping command: %s", command.c_str());
ESP_LOGD(TAG, "Command queue full dropping command: %s", command);
}
void Pipsolar::handle_poll_response_(ENUMPollingCommand polling_command, const char *message) {
+4 -1
View File
@@ -194,7 +194,10 @@ class Pipsolar final : public uart::UARTDevice, public PollingComponent {
PIPSOLAR_SWITCH(pv_ok_condition_for_parallel_switch, QPIRI)
PIPSOLAR_SWITCH(pv_power_balance_switch, QPIRI)
void queue_command(const std::string &command);
void queue_command(const char *command);
void queue_command(const std::string &command) { this->queue_command(command.c_str()); }
// A switch write; off is nullptr when the inverter has no off command
void write_switch(bool state, const char *on, const char *off);
void setup() override;
void loop() override;
void dump_config() override;
+58 -24
View File
@@ -1,10 +1,14 @@
from collections.abc import Callable
from typing import NamedTuple
import esphome.codegen as cg
from esphome.components import switch
import esphome.config_validation as cv
from esphome.const import ICON_POWER
from esphome.cpp_generator import MockObj
from esphome.types import ConfigType
from .. import CONF_PIPSOLAR_ID, PIPSOLAR_COMPONENT_SCHEMA, pipsolar_ns
from .. import CONF_PIPSOLAR_ID, PIPSOLAR_COMPONENT_SCHEMA
DEPENDENCIES = ["uart"]
@@ -16,21 +20,55 @@ CONF_INPUT_VOLTAGE_RANGE = "input_voltage_range"
CONF_PV_OK_CONDITION_FOR_PARALLEL = "pv_ok_condition_for_parallel"
CONF_PV_POWER_BALANCE = "pv_power_balance"
class _PipSwitch(NamedTuple):
setter: Callable[[MockObj], MockObj]
on: str
off: str | None # None when the inverter has no off command
# Each switch's hub setter and its on and off commands
TYPES = {
CONF_OUTPUT_SOURCE_PRIORITY_UTILITY: ("POP00", None),
CONF_OUTPUT_SOURCE_PRIORITY_SOLAR: ("POP01", None),
CONF_OUTPUT_SOURCE_PRIORITY_BATTERY: ("POP02", None),
CONF_OUTPUT_SOURCE_PRIORITY_HYBRID: ("POP03", None),
CONF_INPUT_VOLTAGE_RANGE: ("PGR01", "PGR00"),
CONF_PV_OK_CONDITION_FOR_PARALLEL: ("PPVOKC1", "PPVOKC0"),
CONF_PV_POWER_BALANCE: ("PSPB1", "PSPB0"),
CONF_OUTPUT_SOURCE_PRIORITY_UTILITY: _PipSwitch(
lambda hub: hub.set_output_source_priority_utility_switch,
"POP00",
None,
),
CONF_OUTPUT_SOURCE_PRIORITY_SOLAR: _PipSwitch(
lambda hub: hub.set_output_source_priority_solar_switch,
"POP01",
None,
),
CONF_OUTPUT_SOURCE_PRIORITY_BATTERY: _PipSwitch(
lambda hub: hub.set_output_source_priority_battery_switch,
"POP02",
None,
),
CONF_OUTPUT_SOURCE_PRIORITY_HYBRID: _PipSwitch(
lambda hub: hub.set_output_source_priority_hybrid_switch,
"POP03",
None,
),
CONF_INPUT_VOLTAGE_RANGE: _PipSwitch(
lambda hub: hub.set_input_voltage_range_switch,
"PGR01",
"PGR00",
),
CONF_PV_OK_CONDITION_FOR_PARALLEL: _PipSwitch(
lambda hub: hub.set_pv_ok_condition_for_parallel_switch,
"PPVOKC1",
"PPVOKC0",
),
CONF_PV_POWER_BALANCE: _PipSwitch(
lambda hub: hub.set_pv_power_balance_switch,
"PSPB1",
"PSPB0",
),
}
PipsolarSwitch = pipsolar_ns.class_("PipsolarSwitch", switch.Switch, cg.Component)
PIPSWITCH_SCHEMA = switch.switch_schema(
PipsolarSwitch, icon=ICON_POWER, block_inverted=True
).extend(cv.COMPONENT_SCHEMA)
switch.ApplySwitch, icon=ICON_POWER, block_inverted=True
)
CONFIG_SCHEMA = PIPSOLAR_COMPONENT_SCHEMA.extend(
{cv.Optional(type): PIPSWITCH_SCHEMA for type in TYPES}
@@ -38,15 +76,11 @@ CONFIG_SCHEMA = PIPSOLAR_COMPONENT_SCHEMA.extend(
async def to_code(config: ConfigType) -> None:
paren = await cg.get_variable(config[CONF_PIPSOLAR_ID])
for type, (on, off) in TYPES.items():
if type in config:
conf = config[type]
var = await switch.new_switch(conf)
await cg.register_component(var, conf)
cg.add(getattr(paren, f"set_{type}_switch")(var))
cg.add(var.set_parent(paren))
cg.add(var.set_on_command(on))
if off is not None:
cg.add(var.set_off_command(off))
hub = await cg.get_variable(config[CONF_PIPSOLAR_ID])
switches = switch.sub_switches(config, parent=hub)
# The hub polls the inverter and publishes each switch's state
for key, sw in TYPES.items():
off_arg = "nullptr" if sw.off is None else f'"{sw.off}"'
await switches(
key, sw.setter(hub), apply=f'write_switch(state, "{sw.on}", {off_arg})'
)
@@ -1,17 +0,0 @@
#include "pipsolar_switch.h"
#include "esphome/core/log.h"
#include "esphome/core/application.h"
namespace esphome::pipsolar {
ESPHOME_LOG_TAG(TAG, "pipsolar.switch");
void PipsolarSwitch::dump_config() { LOG_SWITCH("", "Pipsolar Switch", this); }
void PipsolarSwitch::write_state(bool state) {
const char *command = state ? this->on_command_ : this->off_command_;
if (command != nullptr) {
this->parent_->queue_command(command);
}
}
} // namespace esphome::pipsolar
@@ -1,26 +0,0 @@
#pragma once
#include "../pipsolar.h"
#include "esphome/components/switch/switch.h"
#include "esphome/core/component.h"
namespace esphome::pipsolar {
class Pipsolar;
class PipsolarSwitch final : public switch_::Switch, public Component {
public:
void set_parent(Pipsolar *parent) { this->parent_ = parent; }
void set_on_command(const char *command) { this->on_command_ = command; }
void set_off_command(const char *command) { this->off_command_ = command; }
/// Prevent accidental use of std::string which would dangle
void set_on_command(const std::string &command) = delete;
void set_off_command(const std::string &command) = delete;
void dump_config() override;
protected:
void write_state(bool state) override;
const char *on_command_{nullptr};
const char *off_command_{nullptr};
Pipsolar *parent_;
};
} // namespace esphome::pipsolar