20 if ((value_type == 0x1001) && (value_length == 3)) {
25 else if ((value_type == 0x0003) && (value_length == 1)) {
29 else if ((value_type == 0x1004) && (value_length == 2)) {
34 else if ((value_type == 0x1006) && (value_length == 2)) {
39 else if (((value_type == 0x1007) || (value_type == 0x000F)) && (value_length == 3)) {
40 const uint32_t illuminance =
encode_uint24(data[2], data[1], data[0]);
42 result.
is_light = illuminance >= 100;
43 if (value_type == 0x0F)
47 else if ((value_type == 0x1008) && (value_length == 1)) {
51 else if ((value_type == 0x1009) && (value_length == 2)) {
52 const uint16_t conductivity =
encode_uint16(data[1], data[0]);
56 else if ((value_type == 0x100A || value_type == 0x4803) && (value_length == 1)) {
60 else if ((value_type == 0x100D) && (value_length == 4)) {
67 else if ((value_type == 0x1010) && (value_length == 2)) {
68 const uint16_t formaldehyde =
encode_uint16(data[1], data[0]);
72 else if ((value_type == 0x1012) && (value_length == 1)) {
76 else if ((value_type == 0x1013) && (value_length == 1)) {
80 else if ((value_type == 0x1017) && (value_length == 4)) {
81 const uint32_t idle_time =
encode_uint32(data[3], data[2], data[1], data[0]);
84 }
else if ((value_type == 0x1018) && (value_length == 1)) {
88 else if ((value_type == 0x4C01) && (value_length == 4)) {
89 const uint32_t int_number =
encode_uint32(data[3], data[2], data[1], data[0]);
95 else if ((value_type == 0x4C02) && (value_length == 1)) {
99 else if ((value_type == 0x4C08) && (value_length == 4)) {
100 const uint32_t int_number =
encode_uint32(data[3], data[2], data[1], data[0]);
102 std::memcpy(&humidity, &int_number,
sizeof(humidity));
114 ESP_LOGVV(TAG,
"parse_xiaomi_message(): payload is encrypted, stop reading message.");
126 uint8_t payload_offset = 0;
127 bool success =
false;
129 if (payload_length < 4) {
130 ESP_LOGVV(TAG,
"parse_xiaomi_message(): payload has wrong size (%d)!", payload_length);
134 while (payload_length > 3) {
135 if (payload[payload_offset + 1] != 0x10 && payload[payload_offset + 1] != 0x00 &&
136 payload[payload_offset + 1] != 0x4C && payload[payload_offset + 1] != 0x48) {
137 ESP_LOGVV(TAG,
"parse_xiaomi_message(): fixed byte not found, stop parsing residual data.");
141 const uint8_t value_length = payload[payload_offset + 2];
142 if ((value_length < 1) || (value_length > 4) || (payload_length < (3 + value_length))) {
143 ESP_LOGVV(TAG,
"parse_xiaomi_message(): value has wrong size (%d)!", value_length);
147 const uint16_t value_type =
encode_uint16(payload[payload_offset + 1], payload[payload_offset + 0]);
148 const uint8_t *data = &payload[payload_offset + 3];
153 payload_length -= 3 + value_length;
154 payload_offset += 3 + value_length;
163 ESP_LOGVV(TAG,
"parse_xiaomi_header(): no service data UUID magic bytes.");
173 ESP_LOGVV(TAG,
"parse_xiaomi_header(): service data has no DATA flag.");
177 static uint8_t last_frame_count = 0;
178 if (last_frame_count ==
raw[4]) {
179 ESP_LOGVV(TAG,
"parse_xiaomi_header(): duplicate data packet received (%d).",
static_cast<int>(last_frame_count));
183 last_frame_count =
raw[4];
189 if (device_uuid == 0x0098) {
191 result.
name =
"HHCCJCY01";
192 }
else if (device_uuid == 0x01aa) {
194 result.
name =
"LYWSDCGQ";
195 }
else if (device_uuid == 0x015d) {
197 result.
name =
"HHCCPOT002";
198 }
else if (device_uuid == 0x02df) {
200 result.
name =
"JQJCY01YM";
201 }
else if (device_uuid == 0x03dd) {
203 result.
name =
"MUE4094RT";
205 }
else if (device_uuid == 0x0347 ||
206 device_uuid == 0x0B48) {
208 result.
name =
"CGG1";
209 }
else if (device_uuid == 0x03bc) {
211 result.
name =
"GCLS002";
212 }
else if (device_uuid == 0x045b) {
214 result.
name =
"LYWSD02";
215 }
else if (device_uuid == 0x2542) {
217 result.
name =
"LYWSD02MMC";
218 if (
raw.size() == 19)
220 }
else if (device_uuid == 0x040a) {
222 result.
name =
"WX08ZM";
223 }
else if (device_uuid == 0x0576) {
225 result.
name =
"CGD1";
226 }
else if (device_uuid == 0x066F) {
228 result.
name =
"CGDK2";
229 }
else if (device_uuid == 0x055b) {
231 result.
name =
"LYWSD03MMC";
232 }
else if (device_uuid == 0x1203) {
234 result.
name =
"XMWSDJ04MMC";
235 if (
raw.size() == 19)
237 }
else if (device_uuid == 0x07f6) {
239 result.
name =
"MJYD02YLA";
240 if (
raw.size() == 19)
242 }
else if (device_uuid == 0x06d3) {
244 result.
name =
"MHOC303";
245 }
else if (device_uuid == 0x0387) {
247 result.
name =
"MHOC401";
248 }
else if (device_uuid == 0x0A83) {
250 result.
name =
"CGPR1";
251 if (
raw.size() == 19)
253 }
else if (device_uuid == 0x0A8D) {
255 result.
name =
"RTCGQ02LM";
256 if (
raw.size() == 19)
259 ESP_LOGVV(TAG,
"parse_xiaomi_header(): unknown device, no magic bytes.");
267 if ((
raw.size() != 19) && ((
raw.size() < 22) || (
raw.size() > 24))) {
268 ESP_LOGVV(TAG,
"decrypt_xiaomi_payload(): data packet has wrong size (%d)!",
raw.size());
269#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
276 uint8_t mac_reverse[6] = {0};
277 mac_reverse[5] = (uint8_t) (
address >> 40);
278 mac_reverse[4] = (uint8_t) (
address >> 32);
279 mac_reverse[3] = (uint8_t) (
address >> 24);
280 mac_reverse[2] = (uint8_t) (
address >> 16);
281 mac_reverse[1] = (uint8_t) (
address >> 8);
282 mac_reverse[0] = (uint8_t) (
address >> 0);
297 int cipher_pos = (
raw.size() == 19) ? 5 : 11;
299 const uint8_t *v =
raw.data();
301 memcpy(vector.key, bindkey, vector.keysize);
302 memcpy(vector.ciphertext, v + cipher_pos, vector.datasize);
303 memcpy(vector.tag, v +
raw.size() - vector.tagsize, vector.tagsize);
304 memcpy(vector.iv, mac_reverse, 6);
305 memcpy(vector.iv + 6, v + 2, 3);
306 memcpy(vector.iv + 9, v +
raw.size() - 7, 3);
308 mbedtls_ccm_context ctx;
309 mbedtls_ccm_init(&ctx);
311 int ret = mbedtls_ccm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, vector.key, vector.keysize * 8);
313 ESP_LOGVV(TAG,
"decrypt_xiaomi_payload(): mbedtls_ccm_setkey() failed.");
314 mbedtls_ccm_free(&ctx);
318 ret = mbedtls_ccm_auth_decrypt(&ctx, vector.datasize, vector.iv, vector.ivsize, vector.authdata, vector.authsize,
319 vector.ciphertext, vector.plaintext, vector.tag, vector.tagsize);
321 uint8_t mac_address[6] = {0};
322 memcpy(mac_address, mac_reverse + 5, 1);
323 memcpy(mac_address + 1, mac_reverse + 4, 1);
324 memcpy(mac_address + 2, mac_reverse + 3, 1);
325 memcpy(mac_address + 3, mac_reverse + 2, 1);
326 memcpy(mac_address + 4, mac_reverse + 1, 1);
327 memcpy(mac_address + 5, mac_reverse, 1);
328 ESP_LOGVV(TAG,
"decrypt_xiaomi_payload(): authenticated decryption failed.");
329#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
330 char mac_buf[MAC_ADDRESS_PRETTY_BUFFER_SIZE];
334 ESP_LOGVV(TAG,
" MAC address : %s", mac_buf);
338 ESP_LOGVV(TAG,
" Cipher : %s",
format_hex_pretty_to(hex_buf, vector.ciphertext, vector.datasize));
340 mbedtls_ccm_free(&ctx);
345 uint8_t *p = vector.plaintext;
346 for (std::vector<uint8_t>::iterator it =
raw.begin() + cipher_pos; it !=
raw.begin() + cipher_pos + vector.datasize;
354 ESP_LOGVV(TAG,
"decrypt_xiaomi_payload(): authenticated decryption passed.");
355#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERY_VERBOSE
358 ESP_LOGVV(TAG,
" Plaintext : %s, Packet : %d",
361 mbedtls_ccm_free(&ctx);