11static const char *
const TAG =
"pzem6l24";
116static_assert(std::is_trivially_copyable_v<SensorEntry>,
"SENSORS is copied out of flash with memcpy");
119static bool is_register_read(std::span<const uint8_t> request_pdu) {
125 if (!is_register_read(request_pdu)) {
131 if (data.size() != PZEM_PAYLOAD_SIZE) {
132 ESP_LOGW(TAG,
"Invalid data size for PZEM-6L24: expected %zu bytes, got %zu", PZEM_PAYLOAD_SIZE, data.size());
154 if (is_register_read(request_pdu)) {
158 ESP_LOGW(TAG,
"Energy reset failed; the counters were not cleared");
165 const bool available = data !=
nullptr;
173 static constexpr SensorEntry SENSORS[] PROGMEM = {
223 for (
const SensorEntry &flash_entry : SENSORS) {
235 const size_t o = entry.offset;
237 switch (entry.type) {
248 raw =
static_cast<int32_t
>(
encode_uint32(data[o + 3], data[o + 2], data[o + 1], data[o]));
256 if (this->read_input_registers(0x0000, PZEM_REGISTER_COUNT)) {
270 LOG_UPDATE_INTERVAL(
this);
271 LOG_SENSOR(
" ",
"Voltage A", this->
voltage_a_);
272 LOG_SENSOR(
" ",
"Voltage B", this->
voltage_b_);
273 LOG_SENSOR(
" ",
"Voltage C", this->
voltage_c_);
274 LOG_SENSOR(
" ",
"Current A", this->
current_a_);
275 LOG_SENSOR(
" ",
"Current B", this->
current_b_);
276 LOG_SENSOR(
" ",
"Current C", this->
current_c_);
298 LOG_SENSOR(
" ",
"Frequency", this->
frequency_);
314 ESP_LOGW(TAG,
"No valid reading in %u consecutive polls; the readings are now unavailable",
315 MAX_CONSECUTIVE_READ_FAILURES);
330 if (!this->queue_pdu(pdu)) {
sensor::Sensor * active_energy_c_
sensor::Sensor * voltage_b_
sensor::Sensor * apparent_energy_c_
sensor::Sensor * active_power_c_
void publish_(const uint8_t *data)
sensor::Sensor * reactive_energy_b_
sensor::Sensor * reactive_energy_a_
sensor::Sensor * power_factor_c_
sensor::Sensor * power_factor_b_
sensor::Sensor * active_energy_a_
sensor::Sensor * apparent_energy_a_
bool on_no_response(std::span< const uint8_t > request_pdu) override
void reset_energy(ResetPhase phase_option)
sensor::Sensor * reactive_power_c_
sensor::Sensor * total_reactive_power_
sensor::Sensor * reactive_power_a_
uint8_t reads_outstanding_
sensor::Sensor * apparent_power_a_
sensor::Sensor * voltage_a_
sensor::Sensor * current_b_
void on_response(std::span< const uint8_t > request_pdu, std::span< const uint8_t > response_pdu) override
void dump_config() override
sensor::Sensor * total_active_energy_
sensor::Sensor * active_power_a_
sensor::Sensor * total_power_factor_
sensor::Sensor * total_active_power_
sensor::Sensor * reactive_energy_c_
sensor::Sensor * current_a_
uint8_t consecutive_failures_
sensor::Sensor * active_power_b_
sensor::Sensor * total_reactive_energy_
void on_error(std::span< const uint8_t > request_pdu, modbus::ExceptionCode exception_code) override
sensor::Sensor * apparent_energy_b_
void on_not_sent(std::span< const uint8_t > request_pdu) override
void request_failed_(std::span< const uint8_t > request_pdu)
sensor::Sensor * frequency_
sensor::Sensor * total_apparent_energy_
sensor::Sensor * apparent_power_b_
sensor::Sensor * voltage_c_
sensor::Sensor * active_energy_b_
sensor::Sensor * apparent_power_c_
sensor::Sensor * current_c_
sensor::Sensor * total_apparent_power_
sensor::Sensor * power_factor_a_
sensor::Sensor * reactive_power_b_
Base-class for all sensors.
void publish_state(float state)
Publish a new state to the front-end.
std::span< const uint8_t > server_pdu_payload(std::span< const uint8_t > pdu)
Returns the payload portion of a server response PDU: the bytes after the function code,...
uint8_t pdu_function_code(std::span< const uint8_t > pdu)
Function code of a PDU, exception flag masked; 0 for an empty PDU.
constexpr std::array< uint8_t, 3 > build_reset_pdu(ResetPhase phase)
void progmem_memcpy(void *dst, const void *src, size_t len)
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.