From 21c5d6c0903c93ebb1f4d04927f6df3f0b79430d Mon Sep 17 00:00:00 2001 From: Vadim Aleksandrov Date: Tue, 12 Mar 2024 20:37:46 +0300 Subject: [PATCH] Initial commit --- .github/CODEOWNERS | 1 + .github/dependabot.yaml | 10 ++ .github/workflows/hacs.yaml | 29 ++++ .gitignore | 0 .pre-commit-config.yaml | 7 + README.md | 100 ++++++++++++ assets/petoneer-smartdot.png | Bin 0 -> 80138 bytes custom_components/__init__.py | 0 .../petoneer_smartdot/__init__.py | 48 ++++++ custom_components/petoneer_smartdot/button.py | 153 ++++++++++++++++++ .../petoneer_smartdot/config_flow.py | 115 +++++++++++++ custom_components/petoneer_smartdot/const.py | 14 ++ .../petoneer_smartdot/manifest.json | 18 +++ custom_components/petoneer_smartdot/select.py | 56 +++++++ .../petoneer_smartdot/translations/en.json | 39 +++++ hacs.json | 4 + pyproject.toml | 17 ++ 17 files changed, 611 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/dependabot.yaml create mode 100644 .github/workflows/hacs.yaml create mode 100644 .gitignore create mode 100644 .pre-commit-config.yaml create mode 100644 README.md create mode 100644 assets/petoneer-smartdot.png create mode 100644 custom_components/__init__.py create mode 100644 custom_components/petoneer_smartdot/__init__.py create mode 100644 custom_components/petoneer_smartdot/button.py create mode 100644 custom_components/petoneer_smartdot/config_flow.py create mode 100644 custom_components/petoneer_smartdot/const.py create mode 100644 custom_components/petoneer_smartdot/manifest.json create mode 100644 custom_components/petoneer_smartdot/select.py create mode 100644 custom_components/petoneer_smartdot/translations/en.json create mode 100644 hacs.json create mode 100644 pyproject.toml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..203b4db --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @verdel \ No newline at end of file diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..afaf0bb --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,10 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: daily + - package-ecosystem: pip + directory: "/" + schedule: + interval: daily diff --git a/.github/workflows/hacs.yaml b/.github/workflows/hacs.yaml new file mode 100644 index 0000000..cf0d8f2 --- /dev/null +++ b/.github/workflows/hacs.yaml @@ -0,0 +1,29 @@ +name: HACS validation + +on: + push: + pull_request: + +jobs: + hacs: + runs-on: "ubuntu-latest" + name: HACS + steps: + - name: Check out the repository + uses: actions/checkout@v4.1.1 + + - name: HACS validation + uses: "hacs/action@22.5.0" + with: + category: "integration" + ignore: brands + + hassfest: + runs-on: "ubuntu-latest" + name: Hassfest + steps: + - name: Check out the repository + uses: actions/checkout@v4.1.1 + + - name: Hassfest validation + uses: "home-assistant/actions/hassfest@master" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..ca6fcd1 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,7 @@ +repos: + - repo: https://github.com/charliermarsh/ruff-pre-commit + rev: "v0.2.2" + hooks: + - id: ruff + args: [--fix, --exit-non-zero-on-fix] + - id: ruff-format diff --git a/README.md b/README.md new file mode 100644 index 0000000..7628daa --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# Home Assistant custom component for Petoneer SmartDot + +This is a custom component for Home Assistant that allows the control of the Petoneer SmartDot via bluetooth. + +![Petoneer SmartDot](assets/petoneer-smartdot.png) + +# Installation + +This custom component can be installed in two different ways: `manually` or `using HACS` + +## 1. Installation using HACS (recommended) + +This repo is now in [HACS](https://hacs.xyz/). + +1. Install HACS follow the instructions [here](https://hacs.xyz/docs/setup/prerequisites) +2. Search for `Petoneer SmartDot` +3. Install and enjoy automatic updates + +## 2. Manual Installation + +1. Download the `hass-petoneer-smartdot.zip` file from the + [latest release](https://github.com/verdel/hass-petoneer-smartdot/releases/latest). +2. Unpack the release and copy the `custom_components/petoneer_smartdot` directory + into the `custom_components` directory of your Home Assistant + installation. +3. Ensure bluez is installed and accessible from HA (refer to next section) +4. Add the `petoneer_smartdot` as described in next section. + +## Ensure Host bluetooth is accessible from Home-Assistant + +Since version 1.0.0, this component uses the [`bleak`](https://github.com/hbldh/bleak) python library to access bluetooth (as bluepy is not supported from HA 2022.07+). In order to scan and interact with bluetooth devices, bluez utility needs to be installed and the correct permissions must be given to HA: + +- for **Home Assistant Operating System**: + It should be all setup, at least for HA 2022.7+ + +- For **Home Assistant Container** in docker: + + Ensure your host has the `bluetoothctl` binary on the system (coming from `bluez` or `bluez-util` package, depending on the distro). + The docker-compose container (or equivalent docker command) should link _/var/run/dbus_ with host folder through a volume and _NET_ADMIN_ permission is needed. docker compose extract: + + ```yaml + volumes: + - /run/dbus:/run/dbus:ro + cap_add: + - NET_ADMIN + - NET_RAW + network_mode: host + ``` + +- For **Home Assistant Core** installed in a Virtualenv: + + Ensure your host has the `bluetoothctl` binary on the system (coming from `bluez` or `bluez-util` package, depending on the distro). + Make sure the user running HA belongs to the `bluetooth` group. + +# Homeassistant component configuration + +## Adding the device to HA + +You must have the `bluetooth` integration enabled and configured (HA 2022.8+) or a connected ESPhome device running the bluetooth proxy (HA 2022.10+). The Petoneer SmartDot should be automatically discovered and you will receive a notification prompting you to add it. + +The devices can also be added through the `integration menu` UI: + +- In Configuration/Integrations click on the + button, select `Petoneer SmartDot` and you can either scan for the devices or configure the name and mac address manually on the form. + The SmartDot is automatically added and a device is created. + +Please ensure the following steps prior to adding a new SmartDot: + +- The SmartDot must NOT be connected with the official app (or any other device), else HA will not be able to discover it, nor connect to it. +- Some HA integrations still use some bluetooth libraries that take full control of the physical bluetooth adapter, in that case, other ble integration will not have access to it. So to test this component, best to disable all other ble integrations if you are unsure what ble lib they are using. + +# Debugging + +Please ensure the following: + +1. the petoneer_smartdot integration has been removed from HA. +2. HA has access to the bluetooth adapter (follow the section above in not on HAOS). +3. No other bluetooth integration are using something else than bleak library for bluetooth. If unsure, disable them. +4. The logging has been changed in HA to allow debugging of this component and bleak: + In order to get more information on what is going on, the debugging flag can be enabled by placing in the `configuration.yaml` of Home assistant: + + ```yaml + logger: + default: warning + logs: + custom_components.petoneer_smartdot: debug + bleak_retry_connector: debug + bleak: debug + # homeassistant.components.bluetooth: debug # this can help if needed + # homeassistant.components.esphome.bluetooth: debug # this can help if needed + ``` + + NOTE: this will generate A LOT of debugging messages in the logs, so it is not recommended to use for a long time + +5. Restart HA +6. Reinstall the petoneer_smartdot integration and find the SmartDot through a scan. +7. check the logs and report. Thanks + +# Other info + +Originally based on the work by Marco Colombo [hass-addon-petoneer-smartdot](https://github.com/marcomow/hass-addon-petoneer-smartdot). diff --git a/assets/petoneer-smartdot.png b/assets/petoneer-smartdot.png new file mode 100644 index 0000000000000000000000000000000000000000..5c0591ff162dd39ed081dde470576c33115e0199 GIT binary patch literal 80138 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 literal 0 HcmV?d00001 diff --git a/custom_components/__init__.py b/custom_components/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/custom_components/petoneer_smartdot/__init__.py b/custom_components/petoneer_smartdot/__init__.py new file mode 100644 index 0000000..fb30a0c --- /dev/null +++ b/custom_components/petoneer_smartdot/__init__.py @@ -0,0 +1,48 @@ +"""The Petoneer SmartDot integration.""" + +import logging + +from homeassistant.components.bluetooth import async_ble_device_from_address, async_scanner_count +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import CONF_MAC +from homeassistant.core import HomeAssistant +from homeassistant.exceptions import ConfigEntryNotReady + +from .const import DOMAIN, PLATFORMS + +_LOGGER = logging.getLogger(__name__) + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Set up petoneer_smartdot from a config entry.""" + _LOGGER.debug("integration async setup entry: {entry.as_dict()}") + hass.data.setdefault(DOMAIN, {}) + + address = entry.data.get(CONF_MAC) + + ble_device = async_ble_device_from_address(hass, address.upper(), connectable=True) + _LOGGER.debug("BLE device through HA bt: %s", ble_device) + if ble_device is None: + count_scanners = async_scanner_count(hass, connectable=True) + _LOGGER.debug("Count of BLE scanners in HA bt: %s", count_scanners) + if count_scanners < 1: + raise ConfigEntryNotReady( + "No bluetooth scanner detected. \ + Enable the bluetooth integration or ensure an esphome device \ + is running as a bluetooth proxy" + ) + raise ConfigEntryNotReady(f"Could not find Petoneer SmartDot with address {address}") + + hass.data[DOMAIN][entry.entry_id] = {"id": entry.entry_id, "device": ble_device, "mac": address} + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) + return True + + +async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: + """Unload a config entry.""" + _LOGGER.debug("async unload entry") + unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) + if unload_ok: + hass.data[DOMAIN].pop(entry.entry_id) + + return unload_ok diff --git a/custom_components/petoneer_smartdot/button.py b/custom_components/petoneer_smartdot/button.py new file mode 100644 index 0000000..031396c --- /dev/null +++ b/custom_components/petoneer_smartdot/button.py @@ -0,0 +1,153 @@ +import asyncio +import logging + +from bleak import BleakClient, BleakError +from bleak_retry_connector import establish_connection +from homeassistant.components.button import ButtonEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.entity_registry import async_entries_for_config_entry, async_get + +from .const import DOMAIN, MODES, UUID_CONTROL_MODE + +_LOGGER = logging.getLogger(__name__) + + +async def get_select_entity_value(hass, entry_id) -> str | None: + """Get game mode from select entity value.""" + + entity_registry = async_get(hass) + entries = async_entries_for_config_entry(entity_registry, entry_id) + select_entities = [entry for entry in entries if entry.domain == "select"] + + if select_entities: + select_entity_id = select_entities[0].entity_id + select_entity_state = hass.states.get(select_entity_id) + return select_entity_state.state + + return None + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback): + """Setup button entities.""" + + data = hass.data[DOMAIN][entry.entry_id] + async_add_entities([SmartDotStartButtonEntity(hass, entry.entry_id, data), SmartDotStopButtonEntity(data)]) + + +class SmartDotStartButtonEntity(ButtonEntity): + """Petoneer SmartDot button entity for game start.""" + + _attr_should_poll = False + + def __init__(self, hass, entry_id, data) -> None: + """Initialize the button entity.""" + + self._attr_unique_id = f"{data.get('id')}_start_game" + self._attr_name = "Start" + self._attr_icon = "mdi:play" + self._mac = data.get("mac") + self._ble_device = data.get("device") + self._hass = hass + self._entry_id = entry_id + + _LOGGER.debug("Initializing BLE Device %s (%s)", self._ble_device.name, self._mac) + _LOGGER.debug("BLE_device details: %s", self._ble_device.details) + + async def async_press(self) -> None: + """Restore last state when added.""" + game_mode = await get_select_entity_value(self._hass, self._entry_id) + if game_mode is None: + _LOGGER.debug("Select game mode first") + return + _LOGGER.debug("Current game mode: %s", game_mode) + _LOGGER.debug("Connecting") + try: + client = await establish_connection( + client_class=BleakClient, device=self._ble_device, name=self._ble_device.address + ) + except asyncio.TimeoutError: + _LOGGER.error("Connection Timeout error") + except BleakError as err: + _LOGGER.error("Connection: BleakError: %s", err) + + try: + _LOGGER.debug("Sending command") + await client.write_gatt_char( + UUID_CONTROL_MODE, + bytearray.fromhex(MODES[game_mode]), + response=False, + ) + await asyncio.sleep(0.1) + except asyncio.TimeoutError: + _LOGGER.error("Connection Timeout error") + except BleakError as err: + _LOGGER.error("Connection: BleakError: %s", err) + await client.disconnect() + _LOGGER.debug("Disconnected") + + @property + def device_info(self) -> DeviceInfo: + """Return the device info.""" + return DeviceInfo( + identifiers={(DOMAIN, self._mac)}, + name=f"Petoneer SmartDot ({self._mac})", + manufacturer="Petoneer", + model="SmartDot", + ) + + +class SmartDotStopButtonEntity(ButtonEntity): + """Petoneer SmartDot button entity for game stop.""" + + _attr_should_poll = False + + def __init__(self, data) -> None: + """Initialize the button entity.""" + + self._attr_unique_id = f"{data.get('id')}_stop_game" + self._attr_name = "Stop" + self._attr_icon = "mdi:stop" + self._mac = data.get("mac") + self._ble_device = data.get("device") + _LOGGER.debug("Initializing BLE Device %s (%s)", self._ble_device.name, self._mac) + _LOGGER.debug("BLE_device details: {self._ble_device.details}") + + async def async_press(self) -> None: + """Restore last state when added.""" + _LOGGER.debug("Connecting") + try: + client = await establish_connection( + client_class=BleakClient, device=self._ble_device, name=self._ble_device.address + ) + except asyncio.TimeoutError: + _LOGGER.error("Connection Timeout error") + except BleakError as err: + _LOGGER.error("Connection: BleakError: %s", err) + + try: + _LOGGER.debug("Sending command") + await client.write_gatt_char( + UUID_CONTROL_MODE, + bytearray.fromhex(MODES["stop"]), + response=False, + ) + await asyncio.sleep(0.1) + except asyncio.TimeoutError: + _LOGGER.error("Connection Timeout error") + except BleakError as err: + _LOGGER.error("Connection: BleakError: %s", err) + await client.disconnect() + _LOGGER.debug("Disconnected") + + @property + def device_info(self) -> DeviceInfo: + """Return the device info.""" + return DeviceInfo( + identifiers={(DOMAIN, self._mac)}, + name=f"Petoneer SmartDot ({self._mac})", + manufacturer="Petoneer", + model="SmartDot", + ) diff --git a/custom_components/petoneer_smartdot/config_flow.py b/custom_components/petoneer_smartdot/config_flow.py new file mode 100644 index 0000000..46d982f --- /dev/null +++ b/custom_components/petoneer_smartdot/config_flow.py @@ -0,0 +1,115 @@ +"""Config flow for petoneer smartdot""" + +from __future__ import annotations + +import logging +from typing import Any + +import voluptuous as vol +from bleak import BleakError, BleakScanner +from habluetooth.scanner import create_bleak_scanner +from homeassistant import config_entries +from homeassistant.components.bluetooth import BluetoothScanningMode, BluetoothServiceInfoBleak, async_get_scanner +from homeassistant.const import CONF_MAC, CONF_NAME +from homeassistant.data_entry_flow import FlowResult +from homeassistant.helpers import device_registry as dr + +from .const import CONF_ENTRY_MANUAL, CONF_ENTRY_METHOD, CONF_ENTRY_SCAN, DOMAIN + +_LOGGER = logging.getLogger(__name__) + + +async def discover_petoneer_smartdot( + scanner: type[BleakScanner] | None = None, +) -> list[dict[str, Any]]: + """Scanning feature + Scan the BLE neighborhood for an Petoneer SmartDot + This method requires the script to be launched as root + Returns the list of nearby devices + """ + device_list = [] + scanner = scanner if scanner is not None else BleakScanner + + devices = await scanner.discover() + for d in devices: + if d.name == "PetCat": + device_list.append({"ble_device": d, "model": "PetCat"}) + _LOGGER.debug("Found 'PetCat' with mac: %s, details: %s", d.address, d.details) + return device_list + + +class SmartDotFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): # type: ignore + """Handle a config flow for petoneer smartdot.""" + + VERSION = 1 + CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL + + @property + def data_schema(self) -> vol.Schema: + """Return the data schema for integration.""" + return vol.Schema({vol.Required(CONF_NAME): str, vol.Required(CONF_MAC): str}) + + async def async_step_bluetooth(self, discovery_info: BluetoothServiceInfoBleak) -> FlowResult: + """Handle the bluetooth discovery step.""" + _LOGGER.debug("Discovered bluetooth device: %s", discovery_info) + await self.async_set_unique_id(dr.format_mac(discovery_info.address)) + self._abort_if_unique_id_configured() + + self.devices = [f"{discovery_info.address} ({discovery_info.name})"] + return await self.async_step_device() + + async def async_step_user(self, user_input: dict[str, Any] | None = None) -> FlowResult: + """Handle a flow initialized by the user.""" + + if user_input is None: + schema = {vol.Required(CONF_ENTRY_METHOD): vol.In([CONF_ENTRY_SCAN, CONF_ENTRY_MANUAL])} + return self.async_show_form(step_id="user", data_schema=vol.Schema(schema)) + method = user_input[CONF_ENTRY_METHOD] + _LOGGER.debug("Method selected: %s", method) + if method == CONF_ENTRY_SCAN: + return await self.async_step_scan() + else: + self.devices = [] + return await self.async_step_device() + + async def async_step_scan(self, user_input: dict[str, Any] | None = None) -> FlowResult: + """Handle the discovery by scanning.""" + errors = {} + scanner = async_get_scanner(self.hass) + _LOGGER.debug("Preparing for a scan") + try: + if len(scanner.discovered_devices) >= 1: + _LOGGER.debug("Using HA scanner %s", scanner) + except AttributeError: + scanner = create_bleak_scanner(BluetoothScanningMode.ACTIVE, None) + _LOGGER.debug("Using bleak scanner through HA") + try: + _LOGGER.debug("Starting a scan for Petoneer SmartDot devices") + ble_devices = await discover_petoneer_smartdot(scanner) + except BleakError as err: + _LOGGER.error("Bluetooth connection error while trying to scan: %s", err) + errors["base"] = "BleakError" + return self.async_show_form(step_id="scan", errors=errors) + + if not ble_devices: + return self.async_abort(reason="no_devices_found") + self.devices = [f"{dev['ble_device'].address} ({dev['model']})" for dev in ble_devices] + return await self.async_step_device() + + async def async_step_device(self, user_input: dict[str, Any] | None = None) -> FlowResult: + """Handle setting up a device.""" + if not user_input: + schema_mac = str + if self.devices: + schema_mac = vol.In(self.devices) + schema = vol.Schema({vol.Required(CONF_MAC): schema_mac}) + return self.async_show_form(step_id="device", data_schema=schema) + + user_input[CONF_MAC] = user_input[CONF_MAC][:17] + unique_id = dr.format_mac(user_input[CONF_MAC]) + _LOGGER.debug("Petoneer SmartDot ID: %s", unique_id) + + await self.async_set_unique_id(unique_id) + self._abort_if_unique_id_configured() + + return self.async_create_entry(title=unique_id, data=user_input) diff --git a/custom_components/petoneer_smartdot/const.py b/custom_components/petoneer_smartdot/const.py new file mode 100644 index 0000000..5d17851 --- /dev/null +++ b/custom_components/petoneer_smartdot/const.py @@ -0,0 +1,14 @@ +"""Constants for the Petoneer SmartDot integration.""" + +DOMAIN = "petoneer_smartdot" +UUID_CONTROL_MODE = "0000fff3-0000-1000-8000-00805f9b34fb" +MODES = { + "stop": "0f0407000008", + "small": "0f0405000107", + "medium": "0f0405000208", + "large": "0f0405000309", +} +CONF_ENTRY_METHOD = "entry_method" +CONF_ENTRY_SCAN = "Scan" +CONF_ENTRY_MANUAL = "Enter MAC manually" +PLATFORMS: list[str] = ["select", "button"] diff --git a/custom_components/petoneer_smartdot/manifest.json b/custom_components/petoneer_smartdot/manifest.json new file mode 100644 index 0000000..446b3ad --- /dev/null +++ b/custom_components/petoneer_smartdot/manifest.json @@ -0,0 +1,18 @@ +{ + "domain": "petoneer_smartdot", + "name": "Petoneer SmartDot", + "bluetooth": [ + { + "local_name": "PetCat", + "connectable": true + } + ], + "codeowners": ["@verdel"], + "config_flow": true, + "dependencies": ["bluetooth"], + "documentation": "https://github.com/verdel/hass-petoneer-smartdot", + "issue_tracker": "https://github.com/verdel/hass-petoneer-smartdot/issues", + "iot_class": "assumed_state", + "requirements": ["bleak-retry-connector"], + "version": "0.1.0" +} diff --git a/custom_components/petoneer_smartdot/select.py b/custom_components/petoneer_smartdot/select.py new file mode 100644 index 0000000..a4d36ac --- /dev/null +++ b/custom_components/petoneer_smartdot/select.py @@ -0,0 +1,56 @@ +from homeassistant.components.select import SelectEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.device_registry import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.restore_state import RestoreEntity + +from .const import DOMAIN, MODES + + +async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback): + """Setup select entity.""" + + data = hass.data[DOMAIN][entry.entry_id] + async_add_entities([SmartDotSelectEntity(data)]) + + +class SmartDotSelectEntity(SelectEntity, RestoreEntity): + """Petoneer SmartDot select entity for game mode change.""" + + _attr_should_poll = False + + def __init__(self, data) -> None: + """Initialize the game mode select entity.""" + + self._attr_unique_id = f"{data.get('id')}_game_preset" + self._attr_name = "Game preset" + self._attr_translation_key = "preset" + self._attr_options = [key for key in MODES if key != "stop"] + self._attr_icon = "mdi:paw" + self._mac = data.get("mac") + self._attr_current_option = "small" + + async def async_added_to_hass(self) -> None: + """Restore last state when added.""" + last_state = await self.async_get_last_state() + if last_state: + self._attr_current_option = last_state.state + + async def async_select_option(self, option: str) -> None: + """Update the current selected option.""" + if option not in self.options: + raise ValueError(f"Invalid option for {self.entity_id}: {option}") + + self._attr_current_option = option + self.async_write_ha_state() + + @property + def device_info(self) -> DeviceInfo: + """Return the device info.""" + return DeviceInfo( + identifiers={(DOMAIN, self._mac)}, + name=f"Petoneer SmartDot ({self._mac})", + manufacturer="Petoneer", + model="SmartDot", + ) diff --git a/custom_components/petoneer_smartdot/translations/en.json b/custom_components/petoneer_smartdot/translations/en.json new file mode 100644 index 0000000..374bed7 --- /dev/null +++ b/custom_components/petoneer_smartdot/translations/en.json @@ -0,0 +1,39 @@ +{ + "config": { + "step": { + "user": { + "title": "Petoneer SmartDot Bluetooth", + "description": "Control a Petoneer SmartDot devices. Select to scan for devices or enter the MAC address manually.", + "data": { + "entry_method": "Method to be used:" + } + }, + "scan": { + "title": "Petoneer SmartDot Bluetooth", + "description": "Make sure the Petoneer SmartDot device is not connected to other devices or it may not be discoverable (A reset may also help). Are you ready to start scanning?" + }, + "device": { + "title": "Petoneer SmartDot Bluetooth", + "description": "Enter a name for the device and the MAC address for the Petoneer SmartDot device.", + "data": { + "name": "Device Name", + "mac": "MAC address" + } + } + }, + "abort": { + "no_devices_found": "No devices found during this scan. Ensure the Petoneer SmartDot device is not connected to another app." + } + }, + "entity": { + "select": { + "preset": { + "state": { + "small": "Small", + "medium": "Medium", + "large": "Large" + } + } + } + } +} diff --git a/hacs.json b/hacs.json new file mode 100644 index 0000000..84893cc --- /dev/null +++ b/hacs.json @@ -0,0 +1,4 @@ +{ + "name": "Petoneer SmartDot", + "render_readme": true +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..2b34531 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +[tool.ruff] +line-length = 120 +indent-width = 4 + +target-version = "py312" + +[tool.ruff.lint] +select = ["F", "E", "W", "C90", + "I", "N", "S", "B", "A", + "ISC", "T20", "Q", "PTH"] +ignore = ["A003", "C901", "E501"] + +[tool.ruff.format] +quote-style = "double" +indent-style = "space" +skip-magic-trailing-comma = false +line-ending = "auto"