BM6 Battery Monitor ESPHome

Hi @Rafciq
First of all thank you for your work on this, it looks easy to setup and fairly straight forward, but besides many succeeds to make it work, mine just doesn’t want to corporate :slight_smile:
I have an ESP32 Bluetooth proxy running and as soon as I added the BM6 integration, it picked up my QUICKLYNKS Battery Monitory BM6 device, however all the entities are unavailable and no data coming through. I also tried different configurations when first adding the device and that didn’t help.
Is there anything I am missing to configure?
Thank you

I am running them but sometimes they become unavailable then show up again

I’m having a lot of trouble getting mine working. Mine is an ANCEL BM200.
When I try adding the integration, I get the error that “No BM6 devices were found.” I can see the BM6 in my bluetooth integration though, and clicking on it shows the following device information:

Are you using the Bm6 Battery monitor integration?.

Mine says the same when i try to add it (Ancel BM200 & Ancel BM300 Pro), “No BM6 found”.

But when I go into devices & services, it has automatically discovered them.

I have 2 x Ancel BM200 (exactly as yours, same box and all) & 1 Ancel BM300 Pro.

The 200’s show up as BM6 Devices and I get all the info from the sensors.
The Bm300 pro shows as a BM300 pro (BM6 Battery Monitor), but there is no entities shown.

Yes, I am using the BM6 Battery monitor integration.
Unfortunately, nothing comes up in devices and services. Maybe there is an issue with my Shelly being the bluetooth proxy, but I don’t know another way to get bluetooth in my detached garage.

As far as the “interval” for polling the monitor, is the unit of measure seconds or minutes?

I do wonder what it would take to get newer versions supported.

Ancel BM300 Pro

And if you really need it to show BM200 Battery Monitor, rather than BM6.

The following code modified from custom_components\bm6\sensor.py will sort that out.

No other code has been touched, just the manufacturer changed to “Ancel” and the Model changed to “BM200”.

"""Sensor platform for BM6 integration."""

# TODO: Acceleration and deceleration sensors are not implemented yet.

from __future__ import annotations

from typing import TYPE_CHECKING, Any, Dict, Optional, final
import logging

from homeassistant.core import HomeAssistant
from homeassistant.components.sensor import (
    SensorEntity,
    SensorDeviceClass,
    SensorStateClass,
)
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.const import (
    SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
    UnitOfElectricPotential,
    UnitOfTemperature,
    PERCENTAGE,
)

from .const import (
    DOMAIN,
    KEY_BLUETOOTH_SCANNER,
    KEY_CVR_MAX,
    KEY_CVR_MIN,
    KEY_DVR_MAX,
    KEY_DVR_MIN,
    KEY_STATE_ALGORITHM,
    KEY_SOC_MAX,
    KEY_SOC_MIN,
    KEY_SOD_MAX,
    KEY_SOD_MIN,
    KEY_VOLTAGE_CORRECTED,
    KEY_VOLTAGE_DEVICE,
    KEY_TEMPERATURE_CORRECTED,
    KEY_TEMPERATURE_DEVICE,
    KEY_TEMPERATURE_UNIT,
    KEY_PERCENTAGE,
    KEY_STATE,
    KEY_RSSI,
    KEY_DEVICE_PERCENTAGE,
    KEY_DEVICE_STATE,
    KEY_RAPID_ACCELERATION,
    KEY_RAPID_DECELERATION,
    TRANSLATION_KEY_BLUETOOTH_SCANNER,
    TRANSLATION_KEY_VOLTAGE,
    TRANSLATION_KEY_TEMPERATURE,
    TRANSLATION_KEY_PERCENTAGE,
    TRANSLATION_KEY_STATE,
    TRANSLATION_KEY_RSSI,
    TRANSLATION_KEY_DEVICE_PERCENTAGE,
    TRANSLATION_KEY_DEVICE_STATE,
    TRANSLATION_KEY_RAPID_ACCELERATION,
    TRANSLATION_KEY_RAPID_DECELERATION,
)
from .bm6_connect import BM6RealTimeState
from .battery import Battery, BatteryState

if TYPE_CHECKING:
    from . import BM6ConfigEntry
    from .coordinator import BM6DataUpdateCoordinator

_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(
    hass: HomeAssistant,
    config_entry: BM6ConfigEntry,
    async_add_entities: AddEntitiesCallback,
) -> None:
    """Set up BM6 sensors based on a config entry."""
    coordinator = config_entry.runtime_data.coordinator
    await coordinator.async_refresh()

    entities = [
        BM6VoltageSensor(coordinator),
        BM6TemperatureSensor(coordinator),
        BM6PercentageSensor(coordinator),
        BM6StateSensor(coordinator),
        BM6RssiSensor(coordinator),
        BM6DevicePercentageSensor(coordinator),
        BM6DeviceStateSensor(coordinator),
        BM6RapidAccelerationSensor(coordinator),
        BM6RapidDecelerationSensor(coordinator),
        BM6BluetoothScannerSensor(coordinator),
    ]
    async_add_entities(entities)


class BM6SensorEntity(CoordinatorEntity, SensorEntity):
    """Base class for BM6 sensor entities."""

    def __init__(self, coordinator: BM6DataUpdateCoordinator) -> None:
        """Initialize the sensor."""
        super().__init__(coordinator)
        self._attr_extra_state_attributes = {}
        self._device_address = coordinator.device_address

    @property
    def device_info(self) -> DeviceInfo:
        """Return device information."""
        return DeviceInfo(
            identifiers={(DOMAIN, self._device_address)},
            name=f"BM6 {self._device_address}",
            manufacturer="Ancel",
            model="Battery Monitor BM200",
        )

    @property
    def unique_id(self) -> str:
        """Return a unique ID for the sensor."""
        return f"{DOMAIN}_{self._attr_translation_key.lower()}_{self._device_address}"


@final
class BM6VoltageSensor(BM6SensorEntity):
    """Voltage sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_VOLTAGE
    _attr_unit_of_measurement = UnitOfElectricPotential.VOLT
    _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT
    _attr_device_class = SensorDeviceClass.VOLTAGE
    _attr_state_class = SensorStateClass.MEASUREMENT
    _attr_icon = "mdi:flash"

    @property
    def state(self):
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_VOLTAGE_CORRECTED)

    @property
    def native_value(self):
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_VOLTAGE_DEVICE)

    @property
    def extra_state_attributes(self) -> Dict[str, Any]:
        return {
            key: self.coordinator.data.get(key)
            for key in [KEY_VOLTAGE_DEVICE, KEY_VOLTAGE_CORRECTED]
        }


@final
class BM6TemperatureSensor(BM6SensorEntity):
    """Temperature sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_TEMPERATURE
    _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
    _attr_device_class = SensorDeviceClass.TEMPERATURE
    _attr_state_class = SensorStateClass.MEASUREMENT
    _attr_icon = "mdi:thermometer"

    @property
    def state(self):
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_TEMPERATURE_CORRECTED)

    @property
    def native_value(self):
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_TEMPERATURE_DEVICE)

    @property
    def unit_of_measurement(self):
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_TEMPERATURE_UNIT)

    @property
    def extra_state_attributes(self) -> Dict[str, Any]:
        return {
            key: self.coordinator.data.get(key)
            for key in [
                KEY_TEMPERATURE_DEVICE,
                KEY_TEMPERATURE_CORRECTED,
                KEY_TEMPERATURE_UNIT,
            ]
        }


@final
class BM6PercentageSensor(BM6SensorEntity):
    """Percentage sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_PERCENTAGE
    _attr_unit_of_measurement = PERCENTAGE
    _attr_device_class = SensorDeviceClass.BATTERY
    _attr_state_class = SensorStateClass.MEASUREMENT

    @property
    def state(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_PERCENTAGE)

    @property
    def icon(self) -> str:
        return Battery.percent_to_icon(self.state)

    @property
    def extra_state_attributes(self) -> Dict[str, Any]:
        return {
            key: self.coordinator.data.get(key)
            for key in [
                KEY_VOLTAGE_CORRECTED,
                KEY_STATE_ALGORITHM,
                KEY_DVR_MIN,
                KEY_DVR_MAX,
                KEY_CVR_MIN,
                KEY_CVR_MAX,
                KEY_SOD_MIN,
                KEY_SOD_MAX,
                KEY_SOC_MIN,
                KEY_SOC_MAX,
            ]
        }


@final
class BM6StateSensor(BM6SensorEntity):
    """State sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_STATE

    @property
    def native_value(self) -> str:
        """Return the state of the sensor."""
        if self.coordinator.data is None:
            return BatteryState.Unknown.value
        state_str = self.coordinator.data.get(KEY_STATE)
        if state_str in BatteryState._value2member_map_:
            return state_str
        return BatteryState.Unknown.value

    @property
    def icon(self) -> str:
        """Return the icon of the sensor based on the BatteryState."""
        state = self.native_value
        if state == BatteryState.Unknown.value:
            return "mdi:battery-unknown"
        elif state == BatteryState.UnderVoltage.value:
            return "mdi:alert-octagon"
        elif state == BatteryState.Charging.value:
            return "mdi:battery-charging"
        elif state == BatteryState.Idle.value:
            return "mdi:battery-check"
        elif state == BatteryState.Discharging.value:
            return "mdi:battery-arrow-down"
        elif state == BatteryState.OverVoltage.value:
            return "mdi:flash-triangle"
        else:
            return "mdi:battery-unknown"


@final
class BM6RssiSensor(BM6SensorEntity):
    """Signal Strength RSSI sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_RSSI
    _attr_native_unit_of_measurement = SIGNAL_STRENGTH_DECIBELS_MILLIWATT
    _attr_device_class = SensorDeviceClass.SIGNAL_STRENGTH
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_icon = "mdi:wifi"
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_RSSI)


@final
class BM6DevicePercentageSensor(BM6SensorEntity):
    """Device Percentage sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_DEVICE_PERCENTAGE
    _attr_native_unit_of_measurement = PERCENTAGE
    _attr_device_class = SensorDeviceClass.BATTERY
    _attr_state_class = SensorStateClass.MEASUREMENT
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_DEVICE_PERCENTAGE)

    @property
    def icon(self) -> str:
        return Battery.percent_to_icon(self.native_value)


@final
class BM6DeviceStateSensor(BM6SensorEntity):
    """Device State sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_DEVICE_STATE
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_DEVICE_STATE)

    @property
    def state(self) -> str:
        if self.native_value is not None:
            try:
                device_state: BM6RealTimeState = BM6RealTimeState(self.native_value)
                if device_state == BM6RealTimeState.BatteryOk:
                    return BatteryState.Ok.value
                elif device_state == BM6RealTimeState.LowVoltage:
                    return BatteryState.LowVoltage.value
                elif device_state == BM6RealTimeState.Charging:
                    return BatteryState.Charging.value
                elif isinstance(device_state, int):
                    return str(device_state)
            except ValueError:
                if isinstance(device_state, int):
                    return str(device_state)
        return BatteryState.Unknown.value

    @property
    def icon(self) -> str:
        if self.native_value is not None:
            try:
                device_state: BM6RealTimeState = BM6RealTimeState(self.native_value)
                if device_state == BM6RealTimeState.BatteryOk:
                    return "mdi:battery-check"
                elif device_state == BM6RealTimeState.LowVoltage:
                    return "mdi:alert-octagon"
                elif device_state == BM6RealTimeState.Charging:
                    return "mdi:battery-charging"
            except ValueError:
                pass
        return "mdi:battery-unknown"


@final
class BM6BluetoothScannerSensor(BM6SensorEntity):
    """Bluetooth Scanner sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_BLUETOOTH_SCANNER
    _attr_icon = "mdi:bluetooth"
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[str]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_BLUETOOTH_SCANNER)


@final
class BM6RapidAccelerationSensor(BM6SensorEntity):
    """Rapid Acceleration sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_RAPID_ACCELERATION
    # _attr_unit_of_measurement = "mV/s"
    # _attr_device_class = SensorDeviceClass.ACCELERATION
    _attr_state_class = SensorStateClass.MEASUREMENT
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_RAPID_ACCELERATION)


@final
class BM6RapidDecelerationSensor(BM6SensorEntity):
    """Rapid Deceleration sensor."""

    _attr_has_entity_name = True
    _attr_translation_key = TRANSLATION_KEY_RAPID_DECELERATION
    # _attr_unit_of_measurement = "mV/s"
    # _attr_device_class = SensorDeviceClass.ACCELERATION
    _attr_state_class = SensorStateClass.MEASUREMENT
    _attr_entity_category = EntityCategory.DIAGNOSTIC
    _attr_entity_registry_enabled_default = False

    @property
    def native_value(self) -> Optional[int]:
        if self.coordinator.data is None:
            return None
        return self.coordinator.data.get(KEY_RAPID_DECELERATION)

The following modified en.json file from custom_components\bm6\translations\en.json will display the BM6 as Ancel BM200 & the state, percentage & voltage are now displayed in English as well.

{
    "title": "BM200 Battery Monitor",
    "config": {
        "step": {
            "user": {
                "title": "Configuration of the new BM200 monitor",
                "description": "Basic device configuration parameters.",
                "data": {
                    "device_address": "Name/address BM200",
                    "state_algorithm": "Battery calculation algorithm",
                    "update_interval": "Data update interval",
                    "voltage_offset": "Voltage correction",
                    "temperature_offset": "Temperature correction",
                    "temperature_unit": "Temperature unit"
                }
            },
            "custom_calculation": {
                "title": "Configuration of the new BM200 monitor",
                "description": "Battery configuration parameters.",
                "data": {
                    "battery_voltage": "Battery voltage",
                    "battery_type": "Battery type"
                }
            },
            "custom_voltage": {
                "title": "BM200 monitor configuration",
                "description": "Custom battery configuration parameters.",
                "data": {
                    "custom_dvr_min": "Minimum discharging voltage (DVR)",
                    "custom_dvr_max": "Maximum discharging voltage (DVR)",
                    "custom_cvr_min": "Minimum charging voltage (CVR)",
                    "custom_cvr_max": "Maximum charging voltage (CVR)",
                    "custom_soc_min": "Minimum charge voltage (SOC)",
                    "custom_soc_max": "Maximum charge voltage (SOC)",
                    "custom_sod_min": "Minimum discharge voltage (SOD)",
                    "custom_sod_max": "Maximum charge voltage (SOD)"
                }
            }
        },
        "abort": {
            "no_devices_found": "No BM200 devices were found."
        },
        "error": {
            "max_less_than_min": "The maximum voltage value must be greater than the minimum.",
            "cvr_less_than_dvr": "The CVR value must be higher than the DVR value.",
            "soc_less_than_sod": "SOC value must be greater than the value of sod."
        }
    },
    "options": {
        "step": {
            "init": {
                "title": "Re -configuration of the BM200 monitor",
                "description": "Basic device configuration parameters.",
                "data": {
                    "state_algorithm": "Battery calculation algorithm",
                    "update_interval": "Data update interval",
                    "voltage_offset": "Voltage correction",
                    "temperature_offset": "Temperature correction",
                    "temperature_unit": "Temperature unit"
                }
            },
            "custom_calculation": {
                "title": "Configuration of the new BM200 monitor",
                "description": "Battery configuration parameters.",
                "data": {
                    "battery_voltage": "Battery voltage",
                    "battery_type": "Battery type"
                }
            },
            "custom_voltage": {
                "title": "BM200 monitor configuration",
                "description": "Custom battery configuration parameters.",
                "data": {
                    "custom_dvr_min": "Minimum discharging voltage (DVR)",
                    "custom_dvr_max": "Maximum discharging voltage (DVR)",
                    "custom_cvr_min": "Minimum charging voltage (CVR)",
                    "custom_cvr_max": "Maximum charging voltage (CVR)",
                    "custom_soc_min": "Minimum charge voltage (SOC)",
                    "custom_soc_max": "Maximum charge voltage (SOC)",
                    "custom_sod_min": "Minimum discharge voltage (SOD)",
                    "custom_sod_max": "Maximum charge voltage (SOD)"
                }
            }
        },
        "error": {
            "invalid_input": "Incorrect input data.",
            "required_field": "This field is required.",
            "max_less_than_min": "The maximum voltage value must be greater than the minimum.",
            "cvr_less_than_dvr": "The CVR value must be higher than the DVR value.",
            "soc_less_than_sod": "SOC value must be greater than the value of sod."
        }
    },
    "entity": {
        "sensor": {
            "voltage": {
                "name": "Voltage",
                "state_attributes": {
                    "voltage_device": {
                        "name": "Actual Voltage"
                    },
                    "voltage_corrected": {
                        "name": "Corrected voltage"
                    }
                }
            },
            "temperature": {
                "name": "Temperature",
                "state_attributes": {
                    "temperature_device": {
                        "name": "Actual temperature"
                    },
                    "temperature_corrected": {
                        "name": "Corrected temperature"
                    },
                    "temperature_unit": {
                        "name": "Temperature unit"
                    }
                }
            },
            "percentage": {
                "name": "Percent",
                "state_attributes": {
                    "voltage_corrected": {
                        "name": "Corrected voltage"
                    },
                    "percentage": {
                        "name": "Percent"
                    },
                    "state_algorithm": {
                        "name": "Battery calculation algorithm",
                        "state": {
                            "by_device": "Calculated by the BM200 device",
                            "soc_sod": "Calculated from the state of charge/discharge (SOC/SOD)",
                            "cvr_dvr": "Calculated in charging/discharge voltage (CVR/DVR)"
                        }
                    },
                    "dvr_min": {
                        "name": "Minimum Discharging voltage (DVR)"
                    },
                    "dvr_max": {
                        "name": "Maximum Discharging voltage (DVR)"
                    },
                    "cvr_min": {
                        "name": "Minimum charging voltage (CVR)"
                    },
                    "cvr_max": {
                        "name": "Maximum charging voltage (CVR)"
                    },
                    "sod_min": {
                        "name": "Minimum discharge voltage (SOD)"
                    },
                    "sod_max": {
                        "name": "Maximum charge voltage (SOD)"
                    },
                    "soc_min": {
                        "name": "Minimum charge voltage (SOC)"
                    },
                    "soc_max": {
                        "name": "Maximum charge voltage (SOC)"
                    }
                }
            },
            "state": {
                "name": "State",
                "state": {
                    "unknown": "Unknown",
                    "ok": "OK",
                    "low_voltage": "Low voltage",
                    "under_voltage": "Too low voltage",
                    "charging": "Charging",
                    "idle": "Idle",
                    "discharging": "Discharging",
                    "over_voltage": "Too high voltage"
                }
            },
            "rssi": {
                "name": "Signal Strength (RSSI)"
            },
            "device_percentage": {
                "name": "Percentage of the device"
            },
            "device_state": {
                "name": "Condition of the device",
                "state": {
                    "unknown": "Unknown",
                    "ok": "OK",
                    "low_voltage": "Low voltage",
                    "charging": "Charging"
                }
            },
            "rapid_acceleration": {
                "name": "Acceleration"
            },
            "rapid_deceleration": {
                "name": "Slowness"
            },
            "bluetooth_scanner": {
                "name": "Scanner Bluetooth"
            }
        }
    },
    "selector": {
        "battery_voltage": {
            "options": {
                "6v": "6 Volt",
                "12v": "12 Volt"
            }
        },
        "battery_type": {
            "options": {
                "fla": "Flooded acid-alley (FLA)",
                "agm": "Absorbing glass mat (AGM)",
                "gel": "Gel cells (gel)",
                "nicd": "Nickel-cadmia (Nicd)",
                "nimh": "Nickel-metal-water (Nimh)",
                "liion": "Lithium-ion (Li-ion)",
                "lifepo4": "Lithium iron phosphate (Lifepo4)",
                "lto": "Little Titanian (LTO)",
                "custom": "Non -standard battery"
            }
        },
        "battery_state_algorithm": {
            "options": {
                "by_device": "Closed by the BM200 device",
                "soc_sod": "ACCEPTOR FROM THE CHANGE/SENDING STATE (SOC/SOD)",
                "cvr_dvr": "ACCEPLE CHARACTION/SENDING TIME (CVR/DVR)"
            }
        },
        "battery_state": {
            "options": {
                "unknown": "Unknown",
                "ok": "OK",
                "low_voltage": "Low voltage",
                "under_voltage": "Too low voltage",
                "charging": "Charging",
                "idle": "Idle",
                "discharging": "Discharging",
                "over_voltage": "Too high voltage"
            }
        }
    },
    "device_automation": {
        "trigger_type": {
            "start_ok": "OK's condition began",
            "start_low_voltage": "Low voltage has begun",
            "under_voltage": "Too low voltage",
            "start_discharging": "Discharging has begun",
            "start_idle": "The idle mode has begun",
            "start_charging": "Charging began",
            "over_voltage": "Too high voltage",
            "state_changed": "The state has changed"
        }
    }
}

Thanks for this!

Hi would like to know if Ancel bm300 pro can be added into home assistant.
I have installed Battery Monator bm6 and it finds the pro but does not show any data.
I am new to HA ,so I hope someone can point me in the correct direction.

I have this installed but it does not report any values. I think the problem is that my phone and my wife’s phone are still connected to the BM6s on our cars. Should I remove the BM6 app we use or just remove the batteries? I am not sure I understand why this is needed. My wife and I can both be attend to either battery using the app. It seems like this monitor could be a third user of the BM6. What am I not understanding?

What kind of max distance can be expected from the various BM6 units out there?

I’m interested in monitoring some batteries in a boat out on a dock boat lift. It’s probably about 60’ from the nearest structure that has wifi and AC power. It’s about 150’ from the HA server that as a Sena UD100 bluetooth dongle.

@Rafciq - there is a problem with the Bluetooth Wrapper. BleakClient.connect() called without bleak-retry-connector · Issue #28 · Rafciq/BM6

Can you have a look at it please?

This is spamming the Logs with errors.

I had the same problem as a lot of others, worked sometimes for a bit, then stopped.

I’m not a python guy, I spent way to many hours with chatgpt reworking the code. Mine seems to work well now, I have had it running a couple of days with two bm6’s and they don’t seem to be missing any packets. I’m doing 59 and 61 seconds for update rates.

I also added a counter with two automations, they reset it once an hour so I can quickly see if it’s doing ok.

My fork is here if you want to try it, I won’t be able to help if there are any issues. (ask chatgpt :slight_smile: )GitHub - bsrotten/BM6: Home Assistant integration for Battery Monitor BM6

The automations:

alias: BM6 - increment success counter
description: ""
triggers:
  - event_type: bm6_success
    trigger: event
actions:
  - target:
      entity_id: counter.bm6_success_hour
    action: counter.increment
mode: queued


alias: BM6 - reset hourly success counter
description: ""
triggers:
  - minutes: "0"
    trigger: time_pattern
actions:
  - target:
      entity_id: counter.bm6_success_hour
    action: counter.reset
mode: single

I don’t have a garage and my car with BM300 Pro is parked on the street so ESPHome with bluetooth and wifi is not an option.
I saw on aliexpress some seedstudio esp32 WiFi + BLE + LoRa .
Does already exist an ESPHome LoRa Bluetooth proxy that could use 2 of these esp32 to connect the BM300 Pro in the car to Home Assistant at home?

BM300 Pro --bluetooth–> ESP32 in the car --Lora–> ESP32 at home --WiFi–> HomeAssistant

In theory that should be possible I would think.

Hey @B_Rotten, i don’t know if the original project is alive still… but i made an issue in that repo as yours didn’t have issues enabled.

do you think this is something you could implement in your fork? my fork works as a POC… but i think it would be better if a single integration would support multiple devices.

if anyone wants to test the fork or work on changes to submit PR to original Rafciq repo, its here… GitHub - derekpurdy/BM7: Home Assistant integration for Battery Monitor BM7

Thank you so much. Just ordered one and should be here next week.

Is it possible to set the interval to something lower than 30 minutes? Once per day would be enough if the car is parked. Or less to avoid any drainage. Thank you so much again. I will take a look into the code in detail when I am back from vacation :slight_smile: :+1: