Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into watcher
Browse files Browse the repository at this point in the history
# Conflicts:
#	custom_components/battery_notes/sensor.py
  • Loading branch information
andrew-codechimp committed Jan 12, 2024
2 parents cf8160d + fc12dcd commit 6756c3d
Show file tree
Hide file tree
Showing 17 changed files with 611 additions and 58 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/new_device_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ body:
value: |
The battery library is a JSON document at [custom_components/battery_notes/data/library.json](https://github.com/andrew-codechimp/HA-Battery-Notes/blob/main/custom_components/battery_notes/data/library.json)
To contribute, submit your device details via this form and the relevant code changes will be proposed on your behalf.
Note: The manufacturer and model should be exactly what is displayed on the Device screen within Home Assistant.
Note: The title above is not used and can be just a friendly description of the device. Manufacturer and model should be exactly what is displayed on the Device screen within Home Assistant.
To see your devices, click here:
[![Open your Home Assistant instance and show your devices.](https://my.home-assistant.io/badges/devices.svg)](https://my.home-assistant.io/redirect/devices/)
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
[![Downloads][download-latest-shield]](Downloads)
[![License][license-shield]](LICENSE)
[![hacs][hacsbadge]][hacs]
[![Community Forum][forum-shield]][forum]

[![BuyMeACoffee](https://img.shields.io/badge/-buy_me_a%C2%A0coffee-gray?logo=buy-me-a-coffee&style=for-the-badge)](https://www.buymeacoffee.com/codechimp)

Expand All @@ -23,10 +22,10 @@ Track both the battery type and also when the battery was replaced.

Platform | Name | Description
-- | -- | --
`sensor` | Battery Type | Show battery type.
`sensor` | Battery Type | Show battery type with attributes for separation of type & quantity.
`sensor` | Battery last replaced | Date & Time the battery was last replaced.
`button` | Battery replaced | Update Battery last replaced to now.
`service` | Set battery replaced | Update Battery last replaced.
`service` | Set battery replaced | Update Battery last replaced, optionally set a date other than now.

## Installation

Expand Down
45 changes: 44 additions & 1 deletion custom_components/battery_notes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import homeassistant.helpers.config_validation as cv
import voluptuous as vol
import re

from awesomeversion.awesomeversion import AwesomeVersion
from homeassistant.config_entries import ConfigEntry
Expand All @@ -19,6 +20,8 @@
from homeassistant.helpers import device_registry as dr
from homeassistant.util import dt as dt_util

from .config_flow import CONFIG_VERSION

from .discovery import DiscoveryManager
from .library_updater import (
LibraryUpdater,
Expand All @@ -42,7 +45,9 @@
DATA_COORDINATOR,
ATTR_REMOVE,
ATTR_DEVICE_ID,
ATTR_DATE_TIME_REPLACED
ATTR_DATE_TIME_REPLACED,
CONF_BATTERY_TYPE,
CONF_BATTERY_QUANTITY,
)

MIN_HA_VERSION = "2023.7"
Expand Down Expand Up @@ -137,6 +142,44 @@ async def async_remove_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
_LOGGER.debug("Removed Device %s", device_id)


async def async_migrate_entry(hass, config_entry: ConfigEntry):
"""Migrate old config."""
new_version = CONFIG_VERSION

if config_entry.version == 1:
# Version 1 had a single config for qty & type, split them
_LOGGER.debug("Migrating config entry from version %s", config_entry.version)

matches: re.Match = re.search(
r"^(\d+)(?=x)(?:x\s)(\w+$)|([\s\S]+)", config_entry.data[CONF_BATTERY_TYPE]
)
if matches:
_qty = matches.group(1) if matches.group(1) is not None else "1"
_type = (
matches.group(2) if matches.group(2) is not None else matches.group(3)
)
else:
_qty = 1
_type = config_entry.data[CONF_BATTERY_TYPE]

new_data = {**config_entry.data}
new_data[CONF_BATTERY_TYPE] = _type
new_data[CONF_BATTERY_QUANTITY] = _qty

config_entry.version = new_version

hass.config_entries.async_update_entry(
config_entry, title=config_entry.title, data=new_data
)

_LOGGER.info(
"Entry %s successfully migrated to version %s.",
config_entry.entry_id,
new_version,
)

return True

@callback
async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Update options."""
Expand Down
34 changes: 32 additions & 2 deletions custom_components/battery_notes/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
from .const import (
DOMAIN,
CONF_BATTERY_TYPE,
CONF_BATTERY_QUANTITY,
CONF_DEVICE_NAME,
CONF_MANUFACTURER,
CONF_MODEL,
Expand All @@ -39,6 +40,8 @@

_LOGGER = logging.getLogger(__name__)

CONFIG_VERSION = 2

DEVICE_SCHEMA_ALL = vol.Schema(
{
vol.Required(CONF_DEVICE_ID): selector.DeviceSelector(
Expand Down Expand Up @@ -76,7 +79,7 @@
class BatteryNotesFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Config flow for BatteryNotes."""

VERSION = 1
VERSION = CONFIG_VERSION

data: dict

Expand Down Expand Up @@ -133,6 +136,9 @@ async def async_step_user(

library = Library.factory(self.hass)

# Set defaults if not found in library
self.data[CONF_BATTERY_QUANTITY] = 1

device_battery_details = await library.get_device_battery_details(
device_entry.manufacturer, device_entry.model
)
Expand All @@ -146,7 +152,11 @@ async def async_step_user(
)
self.data[
CONF_BATTERY_TYPE
] = device_battery_details.battery_type_and_quantity
] = device_battery_details.battery_type

self.data[
CONF_BATTERY_QUANTITY
] = device_battery_details.battery_quantity

return await self.async_step_battery()

Expand All @@ -172,6 +182,7 @@ async def async_step_battery(self, user_input: dict[str, Any] | None = None):
errors: dict[str, str] = {}
if user_input is not None:
self.data[CONF_BATTERY_TYPE] = user_input[CONF_BATTERY_TYPE]
self.data[CONF_BATTERY_QUANTITY] = int(user_input[CONF_BATTERY_QUANTITY])

device_id = self.data[CONF_DEVICE_ID]
unique_id = f"bn_{device_id}"
Expand Down Expand Up @@ -204,6 +215,16 @@ async def async_step_battery(self, user_input: dict[str, Any] | None = None):
type=selector.TextSelectorType.TEXT
),
),
vol.Required(
CONF_BATTERY_QUANTITY,
default=int(self.data.get(CONF_BATTERY_QUANTITY))
): selector.NumberSelector(
selector.NumberSelectorConfig(
min=1,
max=100,
mode=selector.NumberSelectorMode.BOX
),
),
}
),
errors=errors,
Expand All @@ -220,6 +241,7 @@ def __init__(self, config_entry: ConfigEntry) -> None:
self.source_device_id: str = self.current_config.get(CONF_DEVICE_ID) # type: ignore
self.name: str = self.current_config.get(CONF_NAME)
self.battery_type: str = self.current_config.get(CONF_BATTERY_TYPE)
self.battery_quantity: int = self.current_config.get(CONF_BATTERY_QUANTITY)

async def async_step_init(
self,
Expand All @@ -231,6 +253,7 @@ async def async_step_init(

schema = self.build_options_schema()
if user_input is not None:
user_input[CONF_BATTERY_QUANTITY] = int(user_input[CONF_BATTERY_QUANTITY])
errors = await self.save_options(user_input, schema)
if not errors:
return self.async_create_entry(title="", data={})
Expand Down Expand Up @@ -289,6 +312,13 @@ def build_options_schema(self) -> vol.Schema:
vol.Required(CONF_BATTERY_TYPE): selector.TextSelector(
selector.TextSelectorConfig(type=selector.TextSelectorType.TEXT),
),
vol.Required(CONF_BATTERY_QUANTITY): selector.NumberSelector(
selector.NumberSelectorConfig(
min=1,
max=100,
mode=selector.NumberSelectorMode.BOX
),
),
}
)

Expand Down
1 change: 1 addition & 0 deletions custom_components/battery_notes/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
DOMAIN_CONFIG = "config"

CONF_BATTERY_TYPE = "battery_type"
CONF_BATTERY_QUANTITY = "battery_quantity"
CONF_SENSORS = "sensors"
CONF_ENABLE_AUTODISCOVERY = "enable_autodiscovery"
CONF_USER_LIBRARY = "user_library"
Expand Down
Loading

0 comments on commit 6756c3d

Please sign in to comment.