Skip to content

Instantly share code, notes, and snippets.

@mateuszdrab
Last active February 5, 2025 19:54
Show Gist options
  • Select an option

  • Save mateuszdrab/922c760582fce29d63608a1a405c541b to your computer and use it in GitHub Desktop.

Select an option

Save mateuszdrab/922c760582fce29d63608a1a405c541b to your computer and use it in GitHub Desktop.

Revisions

  1. mateuszdrab revised this gist Jul 28, 2024. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions esphome-renogy-ble.yaml
    Original file line number Diff line number Diff line change
    @@ -10,15 +10,15 @@ esp32_ble_tracker:

    binary_sensor:
    - platform: ble_presence
    mac_address: AC:4D:16:19:28:AC
    mac_address: mac
    name: "BLE Presence"
    entity_category: "DIAGNOSTIC"
    # - platform: template
    # device_class: battery_charging
    # name: "Charging"

    ble_client:
    - mac_address: AC:4D:16:19:28:AC
    - mac_address: mac
    name: Renogy Battery
    id: renogy_battery_bc
    auto_connect: true
  2. mateuszdrab created this gist Jul 28, 2024.
    156 changes: 156 additions & 0 deletions esphome-renogy-ble.yaml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,156 @@
    esp32:
    board: esp32dev
    # framework:
    # type: arduino

    logger:
    level: DEBUG

    esp32_ble_tracker:

    binary_sensor:
    - platform: ble_presence
    mac_address: AC:4D:16:19:28:AC
    name: "BLE Presence"
    entity_category: "DIAGNOSTIC"
    # - platform: template
    # device_class: battery_charging
    # name: "Charging"

    ble_client:
    - mac_address: AC:4D:16:19:28:AC
    name: Renogy Battery
    id: renogy_battery_bc
    auto_connect: true
    on_connect:
    then:
    - logger.log:
    format: "BLE client connected to battery"
    level: DEBUG
    on_disconnect:
    then:
    - logger.log:
    format: "BLE client disconnected from battery"
    level: DEBUG

    interval:
    - interval: 30s
    then:
    - ble_client.ble_write:
    characteristic_uuid: "FFD1"
    service_uuid: "FFD0"

    id: renogy_battery_bc
    value: !lambda return {0x30, 0x03, 0x13, 0xB2, 0x00, 0x06, 0x65, 0x4A};

    sensor:
    - platform: template
    name: "Current"
    id: renogy_battery_current
    device_class: current
    unit_of_measurement: A
    accuracy_decimals: 1

    - platform: template
    name: "Voltage"
    id: renogy_battery_voltage
    device_class: voltage
    unit_of_measurement: V
    accuracy_decimals: 1

    - platform: template
    name: "Present Capacity"
    id: renogy_battery_present_capacity
    unit_of_measurement: Ah
    accuracy_decimals: 1

    - platform: template
    name: "Total Capacity"
    id: renogy_battery_total_capacity
    unit_of_measurement: Ah
    accuracy_decimals: 1

    - platform: template
    name: "Charge Level"
    id: renogy_battery_charge_level
    icon: mdi:percent
    unit_of_measurement: "%"
    accuracy_decimals: 1

    - platform: ble_client
    ble_client_id: renogy_battery_bc
    id: renogy_battery_sensor
    internal: true
    type: characteristic
    service_uuid: FFF0
    characteristic_uuid: FFF1
    notify: true
    update_interval: never

    # on_notify:
    # then:
    # - lambda: |-
    # ESP_LOGD("ble_client.notify", "x: %.2f", x);

    lambda: |-
    int receivedSize = x.size();
    ESP_LOGD("ble_client_lambda", "Received bytes size: %d", receivedSize);
    // Log each byte in the array
    for (size_t i = 0; i < receivedSize; ++i) {
    ESP_LOGD("main", "Byte %d: 0x%02X", i, x[i]);
    }
    if (receivedSize < 17) return NAN;
    // Parse the function
    uint8_t function;
    std::memcpy(&function, &x[1], sizeof(function));
    // function = ntohs(function); // Convert from network byte order to host byte order
    ESP_LOGD("ble_client_lambda", "function: %d", function);
    // Parse the current
    int16_t current;
    std::memcpy(&current, &x[3], sizeof(current));
    current = ntohs(current); // Convert from network byte order to host byte order
    ESP_LOGD("ble_client_lambda", "current: %d", current);
    // Parse the voltage
    uint16_t voltage;
    std::memcpy(&voltage, &x[5], 2);
    voltage = ntohs(voltage); // Convert from network byte order to host byte order
    ESP_LOGD("ble_client_lambda", "voltage: %d", voltage);
    // Parse the present capacity
    uint32_t presentCapacity;
    std::memcpy(&presentCapacity, &x[7], 4);
    presentCapacity = ntohl(presentCapacity); // Convert from network byte order to host byte order
    ESP_LOGD("ble_client_lambda", "presentCapacity: %d", presentCapacity);
    // Parse the total capacity
    uint32_t totalCapacity;
    std::memcpy(&totalCapacity, &x[11], 4);
    totalCapacity = ntohl(totalCapacity); // Convert from network byte order to host byte order
    ESP_LOGD("ble_client_lambda", "totalCapacity: %d", totalCapacity);
    // Convert the values to the appropriate units
    float currentFloat = static_cast<float>(current) / 100.0f;
    float voltageFloat = static_cast<float>(voltage) / 10.0f;
    float presentCapacityFloat = static_cast<float>(presentCapacity) / 1000.0f;
    float totalCapacityFloat = static_cast<float>(totalCapacity) / 1000.0f;
    float chargeLevelFloat = (presentCapacityFloat / totalCapacityFloat) * 100.0f;
    id(renogy_battery_current).publish_state(currentFloat);
    id(renogy_battery_voltage).publish_state(voltageFloat);
    id(renogy_battery_present_capacity).publish_state(presentCapacityFloat);
    id(renogy_battery_total_capacity).publish_state(totalCapacityFloat);
    id(renogy_battery_charge_level).publish_state(chargeLevelFloat);
    ESP_LOGD("ble_client_lambda", "currentFloat: %.1f", currentFloat);
    ESP_LOGD("ble_client_lambda", "voltageFloat: %.1f", voltageFloat);
    ESP_LOGD("ble_client_lambda", "presentCapacityFloat: %.1f", presentCapacityFloat);
    ESP_LOGD("ble_client_lambda", "totalCapacityFloat: %.1f", totalCapacityFloat);
    ESP_LOGD("ble_client_lambda", "chargeLevelFloat: %.1f", chargeLevelFloat);
    return 0.0; // this sensor isn't actually used other than to hook into raw value and publish to template sensors