11 ESP_LOGCONFIG(TAG,
"kamstrup_kmp:");
12 LOG_UPDATE_INTERVAL(
this);
77 msg[3] = command >> 8;
78 msg[4] = command & 0xFF;
86 int buffer_len = msg_len + 2;
87 uint8_t
buffer[buffer_len];
90 for (
int i = 0; i < msg_len; i++) {
95 buffer[buffer_len - 2] = crc >> 8;
96 buffer[buffer_len - 1] = crc & 0xFF;
103 for (
int i = 0; i < buffer_len; i++) {
105 if (tx_msg_len + 2 >=
static_cast<int>(
sizeof(tx_msg))) {
106 ESP_LOGE(TAG,
"TX message overflow");
109 tx_msg[tx_msg_len++] = 0x1b;
110 tx_msg[tx_msg_len++] =
buffer[i] ^ 0xff;
112 if (tx_msg_len + 1 >=
static_cast<int>(
sizeof(tx_msg))) {
113 ESP_LOGE(TAG,
"TX message overflow");
116 tx_msg[tx_msg_len++] =
buffer[i];
120 tx_msg[tx_msg_len++] = 0x0D;
127 size_t buffer_len = 0;
132 while (timeout > 0 && buffer_len <
sizeof(
buffer)) {
138 }
else if (buffer_len == 0) {
142 buffer[buffer_len++] = (uint8_t) data;
147 ESP_LOGE(TAG,
"Error while reading from UART");
155 if (timeout == 0 || buffer_len == 0) {
156 ESP_LOGE(TAG,
"Request timed out");
161 if (
buffer[buffer_len - 1] != 0x0D) {
162 ESP_LOGE(TAG,
"Received invalid message (EOM mismatch received 0x%02X, expected 0x0D)",
buffer[buffer_len - 1]);
167 uint8_t msg[20] = {0};
169 for (
size_t i = 1; i < buffer_len - 1 && msg_len < (int)
sizeof(msg); i++) {
171 msg[msg_len++] =
buffer[i + 1] ^ 0xFF;
174 msg[msg_len++] =
buffer[i];
179 if (msg_len < 2 ||
crc16be(msg, msg_len - 2) !=
encode_uint16(msg[msg_len - 2], msg[msg_len - 1])) {
180 ESP_LOGE(TAG,
"Received invalid message (CRC mismatch)");
191 ESP_LOGE(TAG,
"Received invalid message (message too small)");
195 if (msg[0] != 0x3F || msg[1] != 0x10) {
196 ESP_LOGE(TAG,
"Received invalid message (invalid header received 0x%02X%02X, expected 0x3F10)", msg[0], msg[1]);
200 uint16_t recv_command = msg[2] << 8 | msg[3];
201 if (recv_command != command) {
202 ESP_LOGE(TAG,
"Received invalid message (invalid unexpected command received 0x%04X, expected 0x%04X)",
203 recv_command, command);
207 uint8_t unit_idx = msg[4];
208 uint8_t mantissa_range = msg[5];
210 if (mantissa_range > 4 || msg_len < 7 + mantissa_range) {
211 ESP_LOGE(TAG,
"Received invalid message (mantissa size %d, msg_len %d)", mantissa_range, msg_len);
216 int8_t exp_val = msg[6] & 0x3F;
222 exponent = -exponent;
227 for (
int i = 0; i < mantissa_range; i++) {
229 mantissa |= msg[i + 7];
233 float value = mantissa * exponent;
240 const char *unit = unit_idx <
sizeof(UNITS) /
sizeof(UNITS[0]) ? UNITS[unit_idx] :
"";
245 }
else if (command == CMD_POWER && this->
power_sensor_ !=
nullptr) {
247 }
else if (command == CMD_TEMP1 && this->
temp1_sensor_ !=
nullptr) {
249 }
else if (command == CMD_TEMP2 && this->
temp2_sensor_ !=
nullptr) {
253 }
else if (command == CMD_FLOW && this->
flow_sensor_ !=
nullptr) {
255 }
else if (command == CMD_VOLUME && this->
volume_sensor_ !=
nullptr) {
266 ESP_LOGD(TAG,
"Received value for command 0x%04X: %.3f [%s]", command, value, unit);
sensor::Sensor * power_sensor_
void set_sensor_value_(uint16_t command, float value, uint8_t unit_idx)
std::queue< uint16_t > command_queue_
sensor::Sensor * temp_diff_sensor_
void send_command_(uint16_t command)
sensor::Sensor * flow_sensor_
sensor::Sensor * temp2_sensor_
sensor::Sensor * temp1_sensor_
sensor::Sensor * heat_energy_sensor_
void read_command_(uint16_t command)
std::vector< sensor::Sensor * > custom_sensors_
void parse_command_message_(uint16_t command, const uint8_t *msg, int msg_len)
sensor::Sensor * volume_sensor_
void send_message_(const uint8_t *msg, int msg_len)
std::vector< uint16_t > custom_commands_
void dump_config() override
void publish_state(float state)
Publish a new state to the front-end.
void discard_available()
Read and drop every byte waiting in the receive buffer.
void write_array(const uint8_t *data, size_t len)
ESPHOME_LOG_TAG(TAG, "kamstrup_kmp")
uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc, uint16_t poly, bool refin, bool refout)
constexpr uint16_t encode_uint16(uint8_t msb, uint8_t lsb)
Encode a 16-bit value given the most and least significant byte.
void HOT delay(uint32_t ms)
float pow10_int(int8_t exp)
Compute 10^exp using iterative multiplication/division.