-
-
Notifications
You must be signed in to change notification settings - Fork 22
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Yeelight Rotating Dimmer (YLKG07YL, YLKG08YL) support #32
base: main
Are you sure you want to change the base?
Conversation
8ecd304
to
4744dff
Compare
4229039
to
75de22e
Compare
75de22e
to
b4d2e41
Compare
Will you finish this pr? |
My plan is to refactor this feature to use the new button entity instead of triggers. You could use this version as a custom component in the meantime. It's working. |
@syssi Hi. I am able to connect my dimmer to HA via ble_scanner, but with this PR it does not work. There was some config validator errors due to sensor_schema changes i guess, i fixed that. but i'm still not receiving any advertisements. I am used this guide to make it work with ble_scanner, including extending the bindkey with ffffffff. Maybe that is the problem? |
Is the length of your bindkey different to the one of the example YAML? |
Extracted key has the same length: 5ab9badac3b1becfc5ef5dcd |
@syssi sorry for being annoying, can you suggest something to troubleshoot this? |
Here's what i am receiving from the dimmer:
So device type seems correct(B6.03), but everything else is just a mess with wrong packet size? |
I just realized your hardware model is different to the implemented one, right? |
With some help of chatgpt i am managed to make it work like this: bool decrypt_xiaomi_payload(std::vector<uint8_t> &raw, const uint8_t *bindkey, const uint64_t &address) {
// Check raw data length
if (raw.size() < 15) { // Minimum expected length for valid payload
ESP_LOGVV(TAG, "Invalid data length.");
return false;
}
ESP_LOGVV(TAG, "KEY: %s", format_hex_pretty(bindkey, 16).c_str());
// Convert the MAC address to bytes (little-endian)
std::vector<uint8_t> mac(6);
for (int i = 0; i < 6; ++i) {
mac[i] = (address >> (8 * i)) & 0xFF;
}
// Build nonce: reversed MAC + raw[6:9] + raw[-7:-4]
std::vector<uint8_t> nonce;
nonce.insert(nonce.end(), mac.begin(), mac.end()); // Reverse MAC
nonce.insert(nonce.end(), raw.begin() + 2, raw.begin() + 5); // raw[6:9]
nonce.insert(nonce.end(), raw.end() - 7, raw.end() - 4); // raw[-7:-4]
ESP_LOGVV(TAG, "DATA: %s", format_hex_pretty(raw.data(), raw.size()).c_str());
// Additional authenticated data (AAD)
uint8_t aad[] = {0x11};
// Token (authentication tag)
std::vector<uint8_t> token(raw.end() - 4, raw.end()); // raw[-4:]
// Cipher payload
std::vector<uint8_t> cipherpayload(raw.begin() + 5, raw.end() - 7); // raw[9:-7]
// Initialize mbedTLS CCM context
mbedtls_ccm_context ccm_ctx;
mbedtls_ccm_init(&ccm_ctx);
// Set up the CCM context with the encryption key
if (mbedtls_ccm_setkey(&ccm_ctx, MBEDTLS_CIPHER_ID_AES, bindkey, 128) != 0) {
ESP_LOGVV(TAG, " Failed to set AES key for CCM.");
mbedtls_ccm_free(&ccm_ctx);
return false;
}
// Allocate space for decrypted payload
std::vector<uint8_t> decrypted_payload(cipherpayload.size());
// Perform decryption
int ret = mbedtls_ccm_auth_decrypt(
&ccm_ctx,
cipherpayload.size(),
nonce.data(),
nonce.size(),
aad,
sizeof(aad),
cipherpayload.data(),
decrypted_payload.data(),
token.data(),
token.size()
);
// Free the CCM context
mbedtls_ccm_free(&ccm_ctx);
// Check decryption status
if (ret != 0) {
ESP_LOGVV(TAG, "decrypt_xiaomi_payload(): mbedtls_ccm_star_auth_decrypt failed.");
mbedtls_ccm_free(&ccm_ctx);
return false;
}
raw.resize(5); //trim encrypted data
raw.insert(raw.end(), mac.rbegin(), mac.rend()); //add mac
raw.insert(raw.end(), decrypted_payload.begin(), decrypted_payload.end()); //add decrypted data
ESP_LOGVV(TAG, "DECRYPTED DATA: %s", format_hex_pretty(raw.data(), raw.size()).c_str());
// clear encrypted flag
raw[0] &= ~0x08;
return true;
} |
Closes: #13
TODOs: