ESPHome 2026.10.0-dev
Loading...
Searching...
No Matches
pzemdc.cpp
Go to the documentation of this file.
1#include "pzemdc.h"
2#include "esphome/core/log.h"
3
4namespace esphome::pzemdc {
5
6namespace helpers = modbus::helpers;
7
8static const char *const TAG = "pzemdc";
9
10static const uint8_t PZEM_CMD_RESET_ENERGY = 0x42;
11static const uint8_t PZEM_REGISTER_COUNT = 8; // 8x 16-bit registers
12
13// Register map, see https://github.com/esphome/feature-requests/issues/49#issuecomment-538636809
14// 32-bit values are two registers, low word first.
15static const uint16_t PZEM_REGISTER_VOLTAGE = 0; // 1 register, 0.01 V
16static const uint16_t PZEM_REGISTER_CURRENT = 1; // 1 register, 0.01 A
17static const uint16_t PZEM_REGISTER_POWER = 2; // 2 registers, 0.1 W
18static const uint16_t PZEM_REGISTER_ENERGY = 4; // 2 registers, 1 Wh
19
20void PZEMDC::on_read_input_registers(uint16_t start_address, std::span<const uint16_t> registers,
23 return; // the hub already logs exception responses
24
25 // Publish a sensor if its register(s) are in this response; skipping absent registers keeps this
26 // correct for any read range, so the poll may be split into multiple requests.
27 auto publish_1_register = [&](sensor::Sensor *sensor, uint16_t reg, float divisor) -> void {
28 if (sensor == nullptr)
29 return;
31 sensor->publish_state(*value / divisor);
32 };
33
34 auto publish_2_registers = [&](sensor::Sensor *sensor, uint16_t reg, float divisor) -> void {
35 if (sensor == nullptr)
36 return;
38 sensor->publish_state(*value / divisor);
39 };
40
41 publish_1_register(this->voltage_sensor_, PZEM_REGISTER_VOLTAGE, 100.0f);
42 publish_1_register(this->current_sensor_, PZEM_REGISTER_CURRENT, 100.0f);
43 publish_2_registers(this->power_sensor_, PZEM_REGISTER_POWER, 10.0f);
44 publish_2_registers(this->energy_sensor_, PZEM_REGISTER_ENERGY, 1000.0f);
45}
46
47void PZEMDC::on_custom_response(std::span<const uint8_t> request_pdu, std::span<const uint8_t> response_pdu,
49 // The only custom request this component sends is the energy reset; acknowledge its echo here so
50 // the default unhandled-response warning stays meaningful.
51 if (!request_pdu.empty() && request_pdu[0] == PZEM_CMD_RESET_ENERGY) {
53 ESP_LOGD(TAG, "Energy reset acknowledged");
54 } else {
55 ESP_LOGW(TAG, "Energy reset rejected");
56 }
57 return;
58 }
60}
61
62void PZEMDC::update() { this->read_input_registers(0, PZEM_REGISTER_COUNT); }
64 ESP_LOGCONFIG(TAG,
65 "PZEMDC:\n"
66 " Address: 0x%02X",
67 this->address_);
68 LOG_SENSOR("", "Voltage", this->voltage_sensor_);
69 LOG_SENSOR("", "Current", this->current_sensor_);
70 LOG_SENSOR("", "Power", this->power_sensor_);
71 LOG_SENSOR("", "Energy", this->energy_sensor_);
72}
73
75 const uint8_t pdu[] = {PZEM_CMD_RESET_ENERGY};
76 this->queue_pdu(pdu);
77}
78
79} // namespace esphome::pzemdc
uint8_t status
Definition bl0942.h:8
virtual void on_custom_response(std::span< const uint8_t > request_pdu, std::span< const uint8_t > response_pdu, ResponseStatus status)
Catch-all for custom function codes and anything that is not a standard-conformant transaction (see d...
Definition modbus.cpp:1379
sensor::Sensor * power_sensor_
Definition pzemdc.h:33
void on_read_input_registers(uint16_t start_address, std::span< const uint16_t > registers, modbus::ResponseStatus status) override
Definition pzemdc.cpp:20
void update() override
Definition pzemdc.cpp:62
sensor::Sensor * current_sensor_
Definition pzemdc.h:32
void on_custom_response(std::span< const uint8_t > request_pdu, std::span< const uint8_t > response_pdu, modbus::ResponseStatus status) override
Definition pzemdc.cpp:47
void dump_config() override
Definition pzemdc.cpp:63
sensor::Sensor * voltage_sensor_
Definition pzemdc.h:31
sensor::Sensor * energy_sensor_
Definition pzemdc.h:34
Base-class for all sensors.
Definition sensor.h:47
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:68
constexpr std::optional< RegisterValueType< VALUE_TYPE > > value_at(std::span< const uint16_t > registers, uint16_t start_address, uint16_t address)
The value stored at an absolute register address, or nullopt when it is not wholly inside this respon...
std::optional< ExceptionCode > ResponseStatus
Definition modbus.h:306
bool succeeded(ResponseStatus status)
True when a transaction carried no exception.
Definition modbus.h:309