Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LEVOIT_UART.md
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,7 @@ Room sizes are transmitted as raw integer values derived from square feet.
| Vital (tag `0x10`) | `raw = round(m² × 10.764 × 1.3)` | ESP→MCU |
| Core / Core600S | `raw = round(m² × 10.764 × 3.15)` | ESP→MCU |

Decode (MCU→ESP): `m² = raw / (10.764 × factor)` where factor = 1.3 (Vital) or 3.15 (Core).
Decode (MCU→ESP): `m² = raw / (10.764 × factor)` where factor = 1.3 (Vital) or 3.15 (Core). Core status values are rounded to the nearest whole m² before publishing so values encoded with `round(m² × 10.764 × 3.15)` round-trip at range edges.

---

Expand Down
4 changes: 2 additions & 2 deletions components/levoit/core_commands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "levoit_message.h"
#include "levoit.h"
#include "number/levoit_number.h"
#include "decoder_helpers.h"
#include "esphome/core/log.h"

namespace esphome
Expand Down Expand Up @@ -122,9 +123,8 @@ namespace esphome
auto *num = self->get_number(NumberType::EFFICIENCY_ROOM_SIZE);
if (num != nullptr)
{
// Convert m² → raw MCU value: 1 m² = 10.764 sq ft, MCU uses sq_ft × 3.15
float m2 = num->state;
uint32_t raw = static_cast<uint32_t>(m2 * 10.764f * 3.15f + 0.5f);
uint32_t raw = encode_core_room_size_raw(m2);
uint8_t size_low = raw & 0xFF;
uint8_t size_high = (raw >> 8) & 0xFF;

Expand Down
4 changes: 2 additions & 2 deletions components/levoit/core_status.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ namespace esphome
bool child_lock = payload[14] != 0;
uint8_t fan_auto_mode = payload[15];
uint16_t efficency_area = (uint16_t)((payload[17] << 8) | payload[16]);
float efficency_area_m2 = static_cast<float>(efficency_area) / (10.764f * 3.15f);
float efficency_area_m2 = decode_core_room_size_m2(efficency_area);
bool light_detect = payload[21] != 0;

self->publish_text_sensor(TextSensorType::ERROR_MESSAGE, "Ok");
Expand Down Expand Up @@ -144,7 +144,7 @@ namespace esphome
bool child_lock = payload[13] != 0;
uint8_t fan_auto_mode = payload[14];
uint16_t efficency_area = (payload[16] << 8) | payload[15];
float efficency_area_m2 = static_cast<float>(efficency_area) / (10.764f * 3.15f);
float efficency_area_m2 = decode_core_room_size_m2(efficency_area);
bool display_on = false;
uint8_t fan_speed = 0;
if (model == ModelType::CORE300S)
Expand Down
16 changes: 16 additions & 0 deletions components/levoit/decoder_helpers.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once
#include <string>
#include <cstdint>
#include <cmath>

namespace esphome
{
Expand Down Expand Up @@ -36,5 +37,20 @@ namespace esphome
return std::to_string(secs) + "s";
}

static inline float core_room_size_factor()
{
return 10.764f * 3.15f;
}

static inline uint32_t encode_core_room_size_raw(float m2)
{
return static_cast<uint32_t>(std::round(m2 * core_room_size_factor()));
}

static inline float decode_core_room_size_m2(uint16_t raw)
{
return std::round(static_cast<float>(raw) / core_room_size_factor());
}

} // namespace levoit
} // namespace esphome
5 changes: 2 additions & 3 deletions components/levoit/levoit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,13 @@ namespace esphome
#endif
}

void Levoit::publish_number(NumberType type, uint32_t value)
void Levoit::publish_number(NumberType type, float value)
{
#ifdef USE_NUMBER
auto *nm = numbers_[nt_idx_(type)];
if (!nm)
return;
float fvalue = static_cast<float>(value);
if (nm->has_state() && nm->state == fvalue)
if (nm->has_state() && nm->state == value)
return;
nm->publish_state(value);
#endif
Expand Down
2 changes: 1 addition & 1 deletion components/levoit/levoit.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Levoit : public Component, public uart::UARTDevice {

// called by decoder when device reports status
void publish_switch(SwitchType type, bool state);
void publish_number(NumberType type, uint32_t value);
void publish_number(NumberType type, float value);
void publish_sensor(SensorType type, uint32_t value);
void publish_select(SelectType type, uint32_t value);
void publish_text_sensor(TextSensorType type, const std::string &value);
Expand Down