8static const char *
const TAG =
"pmsx003";
10static const uint8_t START_CHARACTER_1 = 0x42;
11static const uint8_t START_CHARACTER_2 = 0x4D;
13static const uint16_t PMS_STABILISING_MS = 30000;
15static const uint16_t PMS_CMD_MEASUREMENT_MODE_PASSIVE =
17static const uint16_t PMS_CMD_MEASUREMENT_MODE_ACTIVE = 0x0001;
18static const uint16_t PMS_CMD_SLEEP_MODE_SLEEP = 0x0000;
19static const uint16_t PMS_CMD_SLEEP_MODE_WAKEUP = 0x0001;
24 ESP_LOGCONFIG(TAG,
"PMSX003:");
46 ESP_LOGCONFIG(TAG,
" Mode: active continuous (sensor default)");
48 ESP_LOGCONFIG(TAG,
" Mode: passive with sleep/wake cycles");
117 if (!check.has_value()) {
120 this->data_index_ = 0;
122 }
else if (!*check) {
124 this->data_index_ = 0;
134 const uint8_t
byte = this->
data_[index];
136 if (index == 0 || index == 1) {
137 const uint8_t start_char = index == 0 ? START_CHARACTER_1 : START_CHARACTER_2;
138 if (
byte == start_char) {
142 ESP_LOGW(TAG,
"Start character %u mismatch: 0x%02X != 0x%02X", index + 1,
byte, START_CHARACTER_1);
155 ESP_LOGW(TAG,
"Payload length %u doesn't match. Are you using the correct PMSX003 type?", payload_length);
161 const uint16_t total_size = 4 + payload_length;
163 if (index < total_size - 1) {
169 for (uint16_t i = 0; i < total_size - 2; i++) {
175 ESP_LOGW(TAG,
"PMSX003 checksum mismatch! 0x%02X != 0x%02X",
checksum, check);
183 switch (this->
type_) {
189 return payload_length == 28 || payload_length == 20;
192 return payload_length == 28;
194 return payload_length == 36;
200 uint8_t send_data[7] = {
204 uint8_t((data >> 8) & 0xFF),
205 uint8_t((data >> 0) & 0xFF),
212 for (uint8_t i = 0; i < 5; i++) {
215 send_data[5] = (
checksum >> 8) & 0xFF;
216 send_data[6] = (
checksum >> 0) & 0xFF;
218 for (
auto send_byte : send_data) {
239 "Got PM1.0 Standard Concentration: %u µg/m³, PM2.5 Standard Concentration %u µg/m³, PM10.0 Standard "
240 "Concentration: %u µg/m³, PM1.0 Concentration: %u µg/m³, PM2.5 Concentration %u µg/m³, PM10.0 "
241 "Concentration: %u µg/m³",
242 pm_1_0_std_concentration, pm_2_5_std_concentration, pm_10_0_std_concentration, pm_1_0_concentration,
243 pm_2_5_concentration, pm_10_0_concentration);
271 int32_t aqi_value = calculator->
get_aqi(pm_2_5_concentration, pm_10_0_concentration);
277 "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, "
278 "PM2.5 Particles %u Count/0.1L",
279 pm_particles_03um, pm_particles_05um, pm_particles_10um, pm_particles_25um);
287 "Got PM0.3 Particles: %u Count/0.1L, PM0.5 Particles: %u Count/0.1L, PM1.0 Particles: %u Count/0.1L, "
288 "PM2.5 Particles %u Count/0.1L, PM5.0 Particles: %u Count/0.1L, PM10.0 Particles %u Count/0.1L",
289 pm_particles_03um, pm_particles_05um, pm_particles_10um, pm_particles_25um, pm_particles_50um,
302 ESP_LOGD(TAG,
"Got Formaldehyde: %u µg/m^3", formaldehyde);
313 const float humidity = this->
get_16_bit_uint_(temperature_offset + 2) / 10.0f;
315 ESP_LOGD(TAG,
"Got Temperature: %.1f°C, Humidity: %.1f%%",
temperature, humidity);
325 const uint8_t firmware_version = this->
data_[36];
326 const uint8_t error_code = this->
data_[37];
328 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()
AbstractAQICalculator * get_calculator(AQICalculatorType type)
virtual uint16_t get_aqi(uint16_t pm2_5_value, uint16_t pm10_0_value)=0
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_
aqi::AQICalculatorFactory aqi_calculator_factory_
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_
aqi::AQICalculatorType aqi_calc_type_
sensor::Sensor * pm_particles_05um_sensor_
sensor::Sensor * temperature_sensor_
uint16_t get_16_bit_uint_(uint8_t start_index) const
sensor::Sensor * pm_particles_50um_sensor_
uint32_t update_interval_
void send_command_(PMSX0003Command cmd, uint16_t data)
bool check_payload_length_(uint16_t payload_length)
sensor::Sensor * aqi_sensor_
void publish_state(float state)
Publish a new state to the front-end.
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits=1, UARTParityOptions parity=UART_CONFIG_PARITY_NONE, uint8_t data_bits=8)
Check that the configuration of the UART bus matches the provided values and otherwise print a warnin...
bool read_byte(uint8_t *data)
void write_byte(uint8_t data)
@ PMS_CMD_MEASUREMENT_MODE
@ PMS_CMD_MANUAL_MEASUREMENT
@ PMSX003_STATE_STABILISING
Providing packet encoding functions for exchanging data with a remote host.
Application App
Global storage of Application pointer - only one Application can exist.