Skip to content

Commit

Permalink
Merge pull request #129 from mudape/nexter
Browse files Browse the repository at this point in the history
Catching up
  • Loading branch information
mudape authored Jan 13, 2025
2 parents 191323b + d53d1c8 commit 65337b7
Show file tree
Hide file tree
Showing 14 changed files with 401 additions and 497 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/hacs_action.yml
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
name: HACS Action
name: "HACS Validate"

on:
push:
pull_request:

jobs:
hacs:
name: HACS Action
name: "HACS validation"
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v4"
- name: HACS Action
uses: "hacs/action@main"
with:
category: "integration"
ignore: "brands"
30 changes: 16 additions & 14 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,33 @@ on:
types: [published]

jobs:
release_zip_file:
release:
name: Prepare release asset
runs-on: ubuntu-latest
steps:
- name: Check out repository
- name: ⤵️ Check out code from GitHub
uses: actions/checkout@v4

- name: Get version
id: version
uses: home-assistant/actions/helpers/version@master

- name: "Set version number"
- name: 🔢 Adjust version number
shell: bash
run: |
python3 ${{ github.workspace }}/manage/update_manifest.py --version ${{ steps.version.outputs.version }}
- name: ZIP files
version="${{ github.event.release.tag_name }}"
version="${version,,}"
version="${version#v}"
yq e -P -o=json \
-i ".version = \"${version}\"" \
"${{ github.workspace }}/custom_components/iphonedetect/manifest.json"
- name: 📦 Created zipped release package
run: |
cd /home/runner/work/iphonedetect/iphonedetect/custom_components/iphonedetect
cd "${{ github.workspace }}/custom_components/iphonedetect"
zip iphonedetect.zip -r ./
- name: Upload zip to release
uses: svenstaro/upload-release-action@v1-release
- name: ⬆️ Upload zip to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: /home/runner/work/iphonedetect/iphonedetect/custom_components/iphonedetect/iphonedetect.zip
file: "${{ github.workspace }}/custom_components/iphonedetect/iphonedetect.zip"
asset_name: iphonedetect.zip
tag: ${{ github.ref }}
overwrite: true
103 changes: 61 additions & 42 deletions custom_components/iphonedetect/__init__.py
Original file line number Diff line number Diff line change
@@ -1,87 +1,100 @@
"""iPhone Device Tracker"""

from dataclasses import dataclass
from __future__ import annotations

import logging
from datetime import timedelta
from typing import TYPE_CHECKING

from homeassistant.components.device_tracker import CONF_CONSIDER_HOME
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_IP_ADDRESS, Platform
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.const import CONF_DEVICES, CONF_IP_ADDRESS, Platform
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.typing import ConfigType
from homeassistant.helpers.event import async_track_time_interval

from .const import CONF_PROBE_ARP, CONF_PROBE_IP_NEIGH, CONF_PROBE_IPROUTE, DOMAIN
from .const import DOMAIN, PROBE_INTERVAL
from .coordinator import IphoneDetectUpdateCoordinator
from .scanner import _select_probe, ProbeNud, ProbeSubprocess
from .scanner import (
DeviceData,
Scanner,
ScannerException,
async_get_scanner,
async_update_devices,
)

if TYPE_CHECKING:
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType

_LOGGER = logging.getLogger(__name__)

CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)
PLATFORMS = [Platform.DEVICE_TRACKER]
TRACKER_INTERVAL = timedelta(seconds=PROBE_INTERVAL)

@dataclass(slots=True)
class IphoneDetectDomainData:
"""DomainData Dataclass."""

probe: str | None
coordinators: dict[str, IphoneDetectUpdateCoordinator]


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the integration."""
hass.data[DOMAIN] = IphoneDetectDomainData(
probe = await _select_probe(),
coordinators = {}
)
devices: dict[str, DeviceData]
devices = hass.data.setdefault(DOMAIN, {})[CONF_DEVICES] = {}

try:
scanner: Scanner = await async_get_scanner(hass)
except ScannerException as error:
raise PlatformNotReady(error)

async def _update_devices(*_) -> None:
"""Update reachability for all tracked devices."""
await async_update_devices(hass, scanner, devices)

async_track_time_interval(hass, _update_devices, TRACKER_INTERVAL, cancel_on_shutdown=True)

return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up config entries."""
data: IphoneDetectDomainData = hass.data[DOMAIN]
ip: str = entry.options[CONF_IP_ADDRESS]

if data.probe is None:
raise ConfigEntryNotReady("Can't find a tool to use for probing devices.")
elif data.probe == CONF_PROBE_IPROUTE:
probe_cls = ProbeNud(hass, ip, None)
elif data.probe == CONF_PROBE_IP_NEIGH:
probe_cls = ProbeSubprocess(hass, ip, CONF_PROBE_IP_NEIGH)
else:
probe_cls = ProbeSubprocess(hass, ip, CONF_PROBE_ARP)

coordinator = IphoneDetectUpdateCoordinator(hass, probe_cls)
await coordinator.async_config_entry_first_refresh()
_LOGGER.debug("Adding '%s' to tracked devices", entry.options[CONF_IP_ADDRESS])

device = hass.data[DOMAIN][CONF_DEVICES][entry.entry_id] = DeviceData(
ip_address=entry.options[CONF_IP_ADDRESS],
consider_home=timedelta(seconds=entry.options[CONF_CONSIDER_HOME]),
title=entry.title,
)

data.coordinators[entry.entry_id] = coordinator
coordinator = IphoneDetectUpdateCoordinator(hass, device)
await coordinator.async_config_entry_first_refresh()
hass.data[DOMAIN].setdefault("coordinators", {})[entry.entry_id] = coordinator

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(async_reload_options))
entry.async_on_unload(entry.add_update_listener(async_reload_entry))

return True


async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Update options."""
_LOGGER.debug("Reloading entity '%s' with '%s'", entry.title, entry.options)
await hass.config_entries.async_reload(entry.entry_id)


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Handle removal of an entry."""
unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].coordinators.pop(entry.entry_id)
_LOGGER.debug("Removing '%s' from tracked devices", entry.options[CONF_IP_ADDRESS])
hass.data[DOMAIN][CONF_DEVICES].pop(entry.entry_id)

return unload_ok


async def async_reload_options(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Update options."""
await hass.config_entries.async_reload(entry.entry_id)


async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Migrate old config entry to a new format."""

if config_entry.version == 1:
_LOGGER.debug("Migrating from version 1")
# Move IP address from data to option so its easier to change in UI
# Move IP address from data to options
new_options = config_entry.options.copy()
if config_entry.data.get(CONF_IP_ADDRESS):
new_options[CONF_IP_ADDRESS] = config_entry.data[CONF_IP_ADDRESS]
Expand All @@ -91,6 +104,12 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) ->
if not new_unique_id:
new_unique_id = f"{DOMAIN}_{config_entry.title}".lower()

hass.config_entries.async_update_entry(config_entry, unique_id=new_unique_id, data={}, options=new_options, version=2)
hass.config_entries.async_update_entry(
config_entry,
unique_id=new_unique_id,
data={},
options=new_options,
version=2,
)

return True
Loading

0 comments on commit 65337b7

Please sign in to comment.