9static const uint8_t START_CHARACTER_1 = 0x42;
10static const uint8_t START_CHARACTER_2 = 0x4D;
12static const uint16_t STABILISING_MS = 30000;
14static const uint16_t CMD_MEASUREMENT_MODE_PASSIVE =
16static const uint16_t CMD_MEASUREMENT_MODE_ACTIVE = 0x0001;
17static const uint16_t CMD_SLEEP_MODE_SLEEP = 0x0000;
18static const uint16_t CMD_SLEEP_MODE_WAKEUP = 0x0001;
23 ESP_LOGCONFIG(TAG,
"PMSX003:");
45 ESP_LOGCONFIG(TAG,
" Mode: active continuous (sensor default)");
47 ESP_LOGCONFIG(TAG,
" Mode: passive with sleep/wake cycles");
108 [
this, now](uint8_t
byte) {
111 if (!check.has_value()) {
117 }
else if (!*check) {
130 const uint8_t
byte = this->
data_[index];
132 if (index == 0 || index == 1) {
133 const uint8_t start_char = index == 0 ? START_CHARACTER_1 : START_CHARACTER_2;
134 if (
byte == start_char) {
138 ESP_LOGW(TAG,
"Start character %u mismatch: 0x%02X != 0x%02X", index + 1,
byte, start_char);
151 ESP_LOGW(TAG,
"Payload length %u doesn't match. Are you using the correct PMSX003 type?", payload_length);
157 const uint16_t total_size = 4 + payload_length;
159 if (index < total_size - 1) {
168 ESP_LOGW(TAG,
"PMSX003 checksum mismatch! 0x%02X != 0x%02X",
checksum, check);
177 switch (this->
type_) {
179 return payload_length == 28;
181 return payload_length == 20;
184 return payload_length == 28 || payload_length == 20;
187 return payload_length == 28;
189 return payload_length == 36;
192 return payload_length == 28;
198 uint8_t send_data[7] = {
201 static_cast<uint8_t
>(cmd),
202 uint8_t((data >> 8) & 0xFF),
203 uint8_t((data >> 0) & 0xFF),
210 send_data[5] = (
checksum >> 8) & 0xFF;
211 send_data[6] = (
checksum >> 0) & 0xFF;
213 for (
auto send_byte : send_data) {
231 "Got PM1.0 Standard Concentration: %u µg/m³, PM2.5 Standard Concentration %u µg/m³, PM10.0 Standard "
232 "Concentration: %u µg/m³",
233 pm_1_0_std_concentration, pm_2_5_std_concentration, pm_10_0_std_concentration);
238 const uint8_t pc_offset = is_luftmy ? 10 : 16;
245 ESP_LOGD(TAG,
"Got PM1.0 Concentration: %u µg/m³, PM2.5 Concentration %u µg/m³, PM10.0 Concentration: %u µg/m³",
246 pm_1_0_concentration, pm_2_5_concentration, pm_10_0_concentration);
271 "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, "
272 "PM2.5 Particles: %u Count/0.1L",
273 pm_particles_03um, pm_particles_05um, pm_particles_10um, pm_particles_25um);
280 ESP_LOGD(TAG,
"Got PM5.0 Particles: %u Count/0.1L, PM10.0 Particles: %u Count/0.1L", pm_particles_50um,
293 ESP_LOGD(TAG,
"Got Formaldehyde: %u µg/m^3", formaldehyde);
304 const float humidity = this->
get_16_bit_uint_(temperature_offset + 2) / 10.0f;
306 ESP_LOGD(TAG,
"Got Temperature: %.1f°C, Humidity: %.1f%%",
temperature, humidity);
317 const uint8_t firmware_version = this->
data_[firmware_error_code_offset];
318 const uint8_t error_code = this->
data_[firmware_error_code_offset + 1];
320 ESP_LOGD(TAG,
"Got Firmware Version: 0x%02X, Error Code: 0x%02X", firmware_version, error_code);
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void status_clear_warning()
sensor::Sensor * pm_10_0_sensor_
sensor::Sensor * pm_1_0_std_sensor_
void dump_config() override
sensor::Sensor * pm_particles_100um_sensor_
sensor::Sensor * pm_2_5_sensor_
sensor::Sensor * pm_particles_03um_sensor_
sensor::Sensor * formaldehyde_sensor_
sensor::Sensor * pm_2_5_std_sensor_
sensor::Sensor * humidity_sensor_
uint32_t last_transmission_
optional< bool > check_byte_()
sensor::Sensor * pm_1_0_sensor_
sensor::Sensor * pm_particles_10um_sensor_
sensor::Sensor * pm_10_0_std_sensor_
sensor::Sensor * pm_particles_25um_sensor_
sensor::Sensor * pm_particles_05um_sensor_
sensor::Sensor * temperature_sensor_
uint16_t get_16_bit_uint_(uint8_t start_index) const
void send_command_(Command cmd, uint16_t data)
sensor::Sensor * pm_particles_50um_sensor_
uint32_t update_interval_
bool check_payload_length_(uint16_t payload_length)
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_byte(uint8_t data)
bool read_available(F &&on_byte)
Same as read_available_chunks(), calling on_byte(uint8_t) once per byte.
ESPHOME_LOG_TAG(TAG, "pmsx003")
Application App
Global storage of Application pointer - only one Application can exist.
constexpr uint16_t sum16_bytes(const uint8_t *data, size_t len, uint16_t sum=0)
Add up the bytes of data with size len, truncated to 16 bits.