Skip to content
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

Draft
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

syssi
Copy link
Owner

@syssi syssi commented Dec 26, 2021

Closes: #13

TODOs:

  • Make dimmer values accessible (in lambda function?)
  • Migrate to button events if possible
  • Clean up example.yaml
  • Update README + reference bindkey docs

@syssi syssi force-pushed the add-yeedimmer-ylkg07yl-support branch from 8ecd304 to 4744dff Compare December 26, 2021 15:56
@syssi syssi marked this pull request as draft December 26, 2021 16:09
@syssi syssi changed the title Add YLKG07YL support Add Yeelight Rotating Dimmer (YLKG07YL, YLKG08YL) support Dec 26, 2021
@syssi syssi force-pushed the add-yeedimmer-ylkg07yl-support branch from 4229039 to 75de22e Compare December 26, 2021 20:48
@syssi syssi force-pushed the add-yeedimmer-ylkg07yl-support branch from 75de22e to b4d2e41 Compare December 26, 2021 20:48
@marrobHD
Copy link

Will you finish this pr?

@syssi
Copy link
Owner Author

syssi commented May 13, 2022

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.

@voed
Copy link

voed commented Dec 5, 2024

@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?

@syssi
Copy link
Owner Author

syssi commented Dec 6, 2024

Is the length of your bindkey different to the one of the example YAML?

@voed
Copy link

voed commented Dec 6, 2024

Extracted key has the same length: 5ab9badac3b1becfc5ef5dcd
But to make it work with ble_scanner i used to add ffffffff, so i'm not sure if its some protocol difference or just a trick for ble_scanner itself

@voed
Copy link

voed commented Dec 11, 2024

@syssi sorry for being annoying, can you suggest something to troubleshoot this?
My ceiling lamp built on esphome, so it'll be very handy for me to connect the dimmer directly to the lamp through this component.

@voed
Copy link

voed commented Dec 11, 2024

Here's what i am receiving from the dimmer:

[VV][esp32_ble_tracker:434]: Parse Result:
[VV][esp32_ble_tracker:451]:   Address: 70:C9:12:50:D3:5C (PUBLIC)
[VV][esp32_ble_tracker:453]:   RSSI: -39
[VV][esp32_ble_tracker:454]:   Name: ''
[VV][esp32_ble_tracker:481]:   Service data:
[VV][esp32_ble_tracker:482]:     UUID: 0xFE95
[VV][esp32_ble_tracker:483]:     Data: 48.50.B6.03.4F.9E.D6.8B.74.BE.06.0B.00.00.62.42.26.BB (18)
[VV][esp32_ble_tracker:486]:   Adv data: 15.16.95.FE.48.50.B6.03.4F.9E.D6.8B.74.BE.06.0B.00.00.62.42.26.BB (22)
[VV][xiaomi_ylkg07yl:027]: parse_device(): MAC address 70:C9:12:50:D3:5C found.
[VV][xiaomi_ylkg07yl:085]: decrypt_xiaomi_payload(): data packet has wrong size (18)!

So device type seems correct(B6.03), but everything else is just a mess with wrong packet size?

@syssi
Copy link
Owner Author

syssi commented Dec 12, 2024

I just realized your hardware model is different to the implemented one, right?

@voed
Copy link

voed commented Dec 12, 2024

Label on the box/device says YLKG07YL. So looks like it just some new firmware with different protocol. I did a little research and looks like my dimmer has V5 encryption without mac address in the data packet, that's why it requires to extend the encryption key with Fs
image

@voed
Copy link

voed commented Dec 13, 2024

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;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Yeelight Rotating Dimmer (YLKG07YL, YLKG08YL) support
3 participants