ESPHome 2025.5.0
Loading...
Searching...
No Matches
gcja5.cpp
Go to the documentation of this file.
1/* From snooping with a logic analyzer, the I2C on this sensor is broken. I was only able
2 * to receive 1's as a response from the sensor. I was able to get the UART working.
3 *
4 * The datasheet says the values should be divided by 1000, but this must only be for the I2C
5 * implementation. Comparing UART values with another sensor, there is no need to divide by 1000.
6 */
7#include "gcja5.h"
8#include "esphome/core/log.h"
10#include <cstring>
11
12namespace esphome {
13namespace gcja5 {
14
15static const char *const TAG = "gcja5";
16
17void GCJA5Component::setup() { ESP_LOGCONFIG(TAG, "Setting up gcja5..."); }
18
20 const uint32_t now = App.get_loop_component_start_time();
21 if (now - this->last_transmission_ >= 500) {
22 // last transmission too long ago. Reset RX index.
23 this->rx_message_.clear();
24 }
25
26 if (this->available() == 0) {
27 return;
28 }
29
30 // There must now be data waiting
31 this->last_transmission_ = now;
32 uint8_t val;
33 while (this->available() != 0) {
34 this->read_byte(&val);
35 this->rx_message_.push_back(val);
36
37 // check if rx_message_ has 32 bytes of data
38 if (this->rx_message_.size() == 32) {
39 this->parse_data_();
40
41 if (this->have_good_data_) {
42 if (this->pm_1_0_sensor_ != nullptr)
44 if (this->pm_2_5_sensor_ != nullptr)
46 if (this->pm_10_0_sensor_ != nullptr)
48 if (this->pmc_0_3_sensor_ != nullptr)
50 if (this->pmc_0_5_sensor_ != nullptr)
52 if (this->pmc_1_0_sensor_ != nullptr)
54 if (this->pmc_2_5_sensor_ != nullptr)
56 if (this->pmc_5_0_sensor_ != nullptr)
58 if (this->pmc_10_0_sensor_ != nullptr)
60 } else {
61 this->status_set_warning();
62 ESP_LOGV(TAG, "Have 32 bytes but not good data. Skipping.");
63 }
64
65 this->rx_message_.clear();
66 }
67 }
68}
69
71 uint8_t crc = 0;
72
73 for (uint8_t i = 1; i < 30; i++)
74 crc = crc ^ this->rx_message_[i];
75
76 ESP_LOGVV(TAG, "Checksum packet was (0x%02X), calculated checksum was (0x%02X)", this->rx_message_[30], crc);
77
78 return (crc == this->rx_message_[30]);
79}
80
81uint32_t GCJA5Component::get_32_bit_uint_(uint8_t start_index) {
82 return (((uint32_t) this->rx_message_[start_index + 3]) << 24) |
83 (((uint32_t) this->rx_message_[start_index + 2]) << 16) |
84 (((uint32_t) this->rx_message_[start_index + 1]) << 8) | ((uint32_t) this->rx_message_[start_index]);
85}
86
87uint16_t GCJA5Component::get_16_bit_uint_(uint8_t start_index) {
88 return (((uint32_t) this->rx_message_[start_index + 1]) << 8) | ((uint32_t) this->rx_message_[start_index]);
89}
90
92 ESP_LOGVV(TAG, "GCJA5 Data: ");
93 for (uint8_t i = 0; i < 32; i++) {
94 ESP_LOGVV(TAG, " %u: 0b" BYTE_TO_BINARY_PATTERN " (0x%02X)", i + 1, BYTE_TO_BINARY(this->rx_message_[i]),
95 this->rx_message_[i]);
96 }
97
98 if (this->rx_message_[0] != 0x02 || this->rx_message_[31] != 0x03 || !this->calculate_checksum_()) {
99 ESP_LOGVV(TAG, "Discarding bad packet - failed checks.");
100 return;
101 } else {
102 ESP_LOGVV(TAG, "Good packet found.");
103 }
104
105 this->have_good_data_ = true;
106 uint8_t status = this->rx_message_[29];
107 if (!this->first_status_log_) {
108 this->first_status_log_ = true;
109
110 ESP_LOGI(TAG, "GCJA5 Status");
111 ESP_LOGI(TAG, "Overall Status : %i", (status >> 6) & 0x03);
112 ESP_LOGI(TAG, "PD Status : %i", (status >> 4) & 0x03);
113 ESP_LOGI(TAG, "LD Status : %i", (status >> 2) & 0x03);
114 ESP_LOGI(TAG, "Fan Status : %i", (status >> 0) & 0x03);
115 }
116}
117
119
120} // namespace gcja5
121} // namespace esphome
uint8_t status
Definition bl0942.h:8
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_set_warning(const char *message="unspecified")
sensor::Sensor * pm_2_5_sensor_
Definition gcja5.h:40
sensor::Sensor * pm_1_0_sensor_
Definition gcja5.h:39
sensor::Sensor * pmc_1_0_sensor_
Definition gcja5.h:45
uint32_t get_32_bit_uint_(uint8_t start_index)
Definition gcja5.cpp:81
sensor::Sensor * pmc_5_0_sensor_
Definition gcja5.h:47
sensor::Sensor * pmc_0_3_sensor_
Definition gcja5.h:43
sensor::Sensor * pmc_2_5_sensor_
Definition gcja5.h:46
sensor::Sensor * pmc_0_5_sensor_
Definition gcja5.h:44
sensor::Sensor * pmc_10_0_sensor_
Definition gcja5.h:48
uint16_t get_16_bit_uint_(uint8_t start_index)
Definition gcja5.cpp:87
sensor::Sensor * pm_10_0_sensor_
Definition gcja5.h:41
void dump_config() override
Definition gcja5.cpp:118
std::vector< uint8_t > rx_message_
Definition gcja5.h:35
void publish_state(float state)
Publish a new state to the front-end.
Definition sensor.cpp:39
bool read_byte(uint8_t *data)
Definition uart.h:29
mopeka_std_values val[4]
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
Application App
Global storage of Application pointer - only one Application can exist.