Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
fde0217
Refactor config handling in async_setup function
DevLn Oct 8, 2025
5fa24cd
Keep camera session warm instead of sleeping before disconnect
DevLn Jun 13, 2026
2f593af
Don't swallow CancelledError in the MJPEG stream handler
DevLn Jun 13, 2026
717816a
Make entity availability reflect the real connection state
DevLn Jun 13, 2026
63016cb
Seed lamp state from the camera and confirm before committing
DevLn Jun 13, 2026
db24ab9
Fix supported_fn type hint on light entity description
DevLn Jun 13, 2026
87db976
Report real camera streaming state and support turn on/off
DevLn Jun 13, 2026
38c6539
Show the camera IP and device ID in the device-info card
DevLn Jun 14, 2026
2e56ec3
Add integration brand icon (HA camera glyph + PPPP label)
DevLn Jun 14, 2026
3741d7e
Retry setup when the camera is lost during connect
DevLn Jun 15, 2026
219fb2d
Merge branch 'fix/setup-retry-on-connection-loss'
DevLn Jul 4, 2026
a6d3613
Merge branch 'feature/device-info-brand'
DevLn Jul 4, 2026
37441e1
Fix unload/reload lifecycle leaks
DevLn Jul 4, 2026
441d92a
Merge branch 'fix/unload-lifecycle'
DevLn Jul 4, 2026
ab00654
Fix camera/lamp/button entity bugs
DevLn Jul 4, 2026
eca7b0f
Merge branch 'fix/entity-corrections'
DevLn Jul 4, 2026
b32cc04
Fix discovery loop: track task, persist dedup, quiet log spam
DevLn Jul 4, 2026
e234eee
Merge branch 'fix/discovery'
DevLn Jul 4, 2026
8208ff6
Add options flow for per-entry idle-disconnect delay
DevLn Jul 4, 2026
d7ce643
Merge branch 'feature/config-options-flow'
DevLn Jul 4, 2026
aff6ba2
Expose new binary capabilities in Home Assistant
DevLn Jul 4, 2026
38aa2b8
Merge branch 'feature/expose-binary-capabilities'
DevLn Jul 4, 2026
7550b68
Bump aiopppp pin to 0.3.0 and integration to 1.2.0
DevLn Jul 4, 2026
3879ade
Merge branch 'chore/bump-aiopppp-0.3.0'
DevLn Jul 4, 2026
8bf3f97
Fix battery sensor units and sync-time timezone sign
DevLn Aug 23, 2026
6b64d72
Merge branch 'fix/battery-tz-sensors'
DevLn Aug 23, 2026
7a86cc7
Add device-info diagnostic sensors
DevLn Aug 23, 2026
f6c2c68
Merge branch 'feature/ha-diagnostic-sensors'
DevLn Aug 23, 2026
2a4d960
Add two-way audio talk-back service + bump to aiopppp 0.4.0
DevLn Aug 23, 2026
707b135
Merge branch 'feature/ha-talkback'
DevLn Aug 23, 2026
810a004
Sensor cleanup, camera clock/SSID sensors, resolution select
DevLn Aug 24, 2026
2610e23
Merge branch 'feature/ha-sensors-and-resolution'
DevLn Aug 24, 2026
4c23395
Read the resolution only while the camera is streaming
DevLn Aug 25, 2026
f5d6018
Merge branch 'fix/resolution-read-while-streaming'
DevLn Aug 25, 2026
adb91ac
Poll the camera status so battery and power source can change
DevLn Aug 25, 2026
ab1ebef
Merge branch 'feature/status-polling'
DevLn Aug 25, 2026
737e363
Poll only what live entities actually need
DevLn Aug 25, 2026
90ab5b4
Merge branch 'feature/demand-driven-polling'
DevLn Aug 25, 2026
cc55872
Refresh the timezone from the clock response it already contains
DevLn Aug 25, 2026
407face
Merge branch 'feature/tz-from-datetime'
DevLn Aug 25, 2026
c8640d6
Re-read the camera clock after syncing it
DevLn Aug 25, 2026
cd258bb
Merge branch 'fix/sync-time-refresh'
DevLn Aug 25, 2026
40230e7
Report the camera clock as an offset instead of a ticking time
DevLn Aug 25, 2026
bc46593
Merge branch 'feature/clock-offset-sensor'
DevLn Aug 25, 2026
1631752
Number this release 1.2.0 and pin aiopppp 0.3.0
DevLn Aug 25, 2026
7db324e
Merge branch 'chore/version-1.2.0'
DevLn Aug 25, 2026
96ba517
Register info_poll_interval in the YAML schema, refresh README
DevLn Aug 25, 2026
681f970
Merge branch 'fix/config-schema-and-readme'
DevLn Aug 25, 2026
ac45a9d
Fix talk-back on local media, and stop swallowing ffmpeg errors
DevLn Aug 25, 2026
3c29ee4
Merge branch 'fix/talk-media-url'
DevLn Aug 25, 2026
55fe8b2
README: record talk-back as verified in a live Home Assistant
DevLn Aug 25, 2026
d67309d
Merge branch 'docs/talk-verified'
DevLn Aug 25, 2026
3ad466d
README: record HA test results, known issue, and two missing features
DevLn Aug 25, 2026
5e52d92
Merge branch 'docs/ha-features-and-known-issues'
DevLn Aug 25, 2026
1d09187
Drop the uptime sensor and poll the signal sensor properly
DevLn Aug 25, 2026
dd5d2ac
Merge branch 'fix/signal-sensor-dbm'
DevLn Aug 25, 2026
169b2e2
Restore the auth gate on the reboot button
DevLn Aug 25, 2026
05c3332
Merge branch 'fix/reboot-auth-gate'
DevLn Aug 25, 2026
81d97b7
Track real lamp state, and surface device/chip type
DevLn Aug 25, 2026
cb3ce5e
Merge branch 'feature/lamp-state-and-device-type'
DevLn Aug 25, 2026
837fb29
Move the device type to Manufacturer, and show names only
DevLn Aug 25, 2026
3a46fd0
Map device type to Model and chip type to Model ID
DevLn Aug 26, 2026
e7672ad
Device type sensor: report unknown as None, not "Unknown"
DevLn Aug 26, 2026
0ba330d
Mark every lamp assumed-state, including the ones that report
DevLn Aug 26, 2026
b756857
Add a human-readable clock offset sensor
DevLn Aug 26, 2026
5a14380
Clock offset: one sensor, readable state, number in an attribute
DevLn Aug 26, 2026
38d9088
Clock offset: use the duration device class, keep the number
DevLn Aug 26, 2026
0c40f04
Clock offset: display whole seconds
DevLn Aug 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 168 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,37 @@ These cameras typically use the **Peer-to-Peer protocol** for communication, and

## Features

- Supports A9, X5, and similar PPPP protocol cameras (Only JSON protocol is supported for now)
- Supports A9, X5, and similar PPPP protocol cameras, over **both the JSON and
the binary control protocol** (binary is currently the better-tested path)
- Live streaming via aiopppp
- Snapshot support
- PTZ control through actions/services
- PTZ control through actions/services, including preset slots
- White lights and IR lights control
- **Talk-back**: play a media or TTS source through the camera speaker
- Video resolution as a config entity (dropdown) — see
[Known issues](#known-issues)
- Diagnostic sensors: battery, power source, Wi-Fi signal, SD card usage,
Wi-Fi network, camera clock offset and timezone
- Camera clock sync button
- On-demand connections — the camera is only held open while something needs
it, because these cameras accept **one client at a time**
- Automatic reconnection with backoff when a camera drops off the network
- Support for webrtc custom component
- Automatic device discovery
- (TBD) Sound streaming
- Automatic device discovery, probing with both the plain and the extended
PPPP search packet — some firmwares only answer the extended one
- (TBD) Listening to camera audio in Home Assistant — the library supports it,
but the HA camera entity streams video only

## Tested camera prefixes

| Prefix | Protocol | Video | [Audio<sup>*</sup>](https://github.com/devbis/aiopppp/issues/6) | PTZ | White Light | IR Light | Reboot |
|:---------|:---------|:-----:|:---------------------------------------------------------------:|:---:|:-----------:|:--------:|:------:|
| **DGOK** | 📜 JSON | ✅ | ✖️ | ✅ | ✅ | ✅ | ✅ |
| **PTZA** | 🔢 Binary| ✅ | ✖️ | ✅ | ✅ | 🚫 | ✅ |
| **FTYC** | 🔢 Binary| [❌<sup>*</sup>](https://github.com/devbis/aiopppp/issues/8)| ✖️ | 🚫 | 🚫 | ✅ | ✅ |
| [**BATE**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/4) | 🔢 Binary|❔ |✖️ | ❔ | ❔ | ❔ | ❔ |
| [**DGB**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/2) | 📜 JSON |⚠️ |✖️ | ❔ | ❔ | | ❔ |
| [**ACCQ**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/1) | ❔ Unknown|✖️|✖️ | ✖️ | ✖️ | ✖️ | ✖️ |
| Prefix | Protocol | Video | Snapshot | PTZ | White Light | IR Light | Reboot | Resolution | Talk | Time sync |
|:---------|:---------|:-----:|:--------:|:---:|:-----------:|:--------:|:------:|:----------:|:----:|:---------:|
| **DGOK** | 📜 JSON | ✅ | | ✅ | ✅ | ✅ | ✅ | ✖️ | ✖️ | ✖️ |
| **PTZA** | 🔢 Binary| ✅ | | ✅ | ✅ | 🚫 | ✅ | ✅ | ✅ | ✅ |
| **FTYC** | 🔢 Binary| ✅ | ✅ | 🚫 | 🚫 | ✅ | ✅ | ✅ | 🚫 | ⚠️ |
| [**BATE**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/4) | 🔢 Binary|❔ |❔ | ❔ | ❔ | ❔ | ❔ | | ❔ | ❔ |
| [**DGB**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/2) | 📜 JSON |⚠️ |❔ | ❔ | ❔ | ❔ | ❔ | | ✖️ | ✖️ |
| [**ACCQ**<sup>*</sup>](https://github.com/devbis/pppp_camera/issues/1) | ❔ Unknown|✖️|✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ | ✖️ |

**Legend:**
- &nbsp;✅&nbsp; **Working**: Feature is fully functional.
Expand All @@ -35,6 +47,85 @@ These cameras typically use the **Peer-to-Peer protocol** for communication, and
- &nbsp;🚫&nbsp; **Not supported**: Feature is not supported by the device.
- &ensp;❔ &nbsp; **Not tested**: Feature has not been tested on the device.

Notes: FTYC has no speaker, so talk-back cannot be tested there. FTYC time
sync sets the clock but has no timezone field to write, so its UTC offset
stays whatever the vendor app configured. JSON cameras expose no set-time
command. PTZ presets are sent using the scheme found in the vendor app, but
none of the tested cameras act on them — see
[services](#services) below.

> **Status:** the capability matrix above is what the underlying `aiopppp`
> library was verified to do against real cameras. The Home Assistant side —
> camera, lamps, buttons, diagnostic sensors, resolution select, clock sync,
> talk-back, the services, discovery and the config/options flows — has now
> been exercised in a running Home Assistant against PTZA and FTYC cameras.
> The only entity still unverified is **SD card usage**, for want of a card.

## Known issues

- **A resolution chosen while the camera is idle is overwritten with HD when
the stream starts.** The library sets HD at stream start and deliberately
re-asserts it a few seconds in (the cameras otherwise self-downgrade and
ignore the value set at start time), so an idle selection never survives.
Set the resolution *while the stream is running* and it sticks. Note the
same re-request path runs after a video stall, so a mid-stream stall can
also revert the resolution to HD.

Fixing it means teaching the library to prefer a chosen resolution instead
of the hardcoded default, and having the integration re-apply that choice
on connect so it survives the idle session teardown. Not implemented yet.

## Entities

One device is created per camera. Which entities appear depends on what the
camera actually reports, so a mains-powered camera gets no battery sensor and a
camera without an SD card gets no usage sensor.

| Entity | Platform | Notes |
|:-------|:---------|:------|
| Camera | `camera` | Live stream, snapshots, and turn on/off (starts and stops the video stream) |
| White Lamp / IR Lamp | `switch`, `light` or `button` | Only for cameras reporting that lamp. The platform is chosen by the `platform.lamp` option. Cameras that report real lamp state (function bitmap in the status block) track it live, so changes made from the vendor app show up; the rest assume their own writes. All lamps are marked assumed-state either way — these cameras report fields that look populated but aren't often enough that a toggle would overstate what we know |
| Reboot | `button` | Only when logged in — the camera refuses it otherwise |
| Sync time | `button` | Binary-protocol cameras only |
| Resolution | `select` | Binary-protocol cameras only. QVGA / VGA / HD / FD / UD |
| Battery | `sensor` | Only when the camera reports a real battery voltage |
| Power source | `sensor` | External or Battery. Only alongside a battery reading — mains-only cameras leave the field unpopulated rather than reporting "external" |
| Clock offset | `sensor` | Seconds the camera clock is ahead (+) or behind (−) Home Assistant. A `duration` sensor, so the displayed unit can be changed per entity (seconds → hours) in its settings. Attributes: `offset_text` (`-4 h 52 m 59 s`) and `camera_time` |
| Wi-Fi network | `sensor` | SSID the camera is joined to |
| Timezone | `sensor` | Disabled by default. Not created for firmwares that don't store one |
| Signal strength | `sensor` | Wi-Fi RSSI in dBm. Disabled by default. Not created when the firmware reports no usable value |
| SD card usage | `sensor` | Disabled by default. Only when a card is present |
| Device type | `sensor` | Disabled by default. `DevType (ChipType)`, e.g. `BK_A9 (TX_817_810)` — just the known half if only one is named, unknown if neither. `devType`/`devTypeName`/`chipType`/`chipTypeName` as attributes |

All sensors are diagnostic entities; the resolution select and the reboot/sync
buttons are config entities.

### Polling

These cameras push nothing, and only one client may be connected at a time, so
values are refreshed by briefly opening a session on a timer. Polling is
**demand-driven**: a group of values is only fetched while at least one enabled
entity actually uses it.

| Group | Values | Default interval |
|:------|:-------|:-----------------|
| Status | Battery, power source, signal strength, SD usage | 300 s |
| Info | Camera clock offset, Wi-Fi SSID | 3600 s |

So a camera with no battery and no SD card is never status-polled, and
disabling those entities stops the polling too. Set either interval to `0` to
disable it outright. The timezone sensor never triggers a poll of its own — it
rides along on the clock response, which already carries it.

## Services

| Service | Description |
|:--------|:------------|
| `pppp_camera.ptz` | Pan (`LEFT`/`RIGHT`) or tilt (`UP`/`DOWN`) the camera |
| `pppp_camera.ptz_preset` | Move to (`goto`) or store (`set`) a preset slot, 0–255. Implemented from the vendor app, but **no tested camera acts on it** |
| `pppp_camera.reboot` | Reboot the camera |
| `pppp_camera.talk` | Play an audio media or TTS source through the camera speaker |

## Installation

### Prerequisites
Expand All @@ -55,6 +146,10 @@ Or manually copy pppp_camera folder to custom_components folder in your config f
Add cameras through Home Assistant's **Devices & Services** interface by camera IP address.
If username and passwords are blank, it will use default values for authentication: `admin:6666`.

Per-camera settings (connection and polling behaviour) are available afterwards
via **Configure** on the integration entry, and override the YAML defaults
below.

### Advanced YAML Configuration (Optional)

For advanced configuration options, you can add the following to your `configuration.yaml` file:
Expand All @@ -77,6 +172,9 @@ pppp_camera:
# or single IP can also be specified (usually broadcast address)
ip: 192.168.1.255
# if 'ip' is not specified, discovery will listen on all interfaces
idle_disconnect_delay: 5 # seconds to keep a session warm after the last operation
status_poll_interval: 300 # seconds between battery/signal/SD refreshes
info_poll_interval: 3600 # seconds between clock/SSID refreshes
```

### Configuration Parameters
Expand Down Expand Up @@ -106,6 +204,31 @@ Configure automatic device discovery on your network.
- Can be a list of specific IP addresses
- If not specified, discovery listens on all available network interfaces

#### `idle_disconnect_delay` (optional)

- **`idle_disconnect_delay`** (integer, default: `5`): Seconds to keep a camera
session open after the last in-flight operation completes. These cameras allow
only one client at a time, so the session is opened on demand and released when
idle. Keeping it warm briefly lets back-to-back commands (e.g. PTZ bursts) reuse
the session and prevents a fire-and-forget command from being cut off by an
immediate disconnect. Set to `0` to disconnect immediately after each operation.

#### `status_poll_interval` (optional)

- **`status_poll_interval`** (integer, default: `300`): Seconds between refreshes
of battery, power source, signal strength and SD card usage. Only polled while at least
one of those entities is enabled, so a camera without a battery or SD card is
never contacted for them. Set to `0` to disable.

#### `info_poll_interval` (optional)

- **`info_poll_interval`** (integer, default: `3600`): Seconds between refreshes
of the camera clock and Wi-Fi network. These barely change — the SSID only when
the camera is re-provisioned — so this is deliberately much slower than the
status poll. Set to `0` to disable.

All four of the above can also be set per camera from the integration's
**Configure** dialog, which takes precedence over the YAML values.

## Usage

Expand All @@ -123,6 +246,24 @@ target:
entity_id: camera.dgok_123456_xxxxx
```

Talk-back plays any media or TTS source through the camera speaker:

```yaml
action: pppp_camera.talk
data:
media:
media_content_id: media-source://tts/tts.google_en_com?message=Someone+is+at+the+door
media_content_type: provider
target:
entity_id: camera.ptza_123456_xxxxx
```

The easiest way to try it is **Developer tools → Actions → Talk**, picking a
short file with the media browser (anything ffmpeg can decode works; it is
transcoded to the 8 kHz mono the camera expects). Note that the action runs for
as long as the audio lasts — it is streamed to the camera in real time — so
test with a few seconds of audio rather than a full song. The camera must
actually have a speaker; not all models do.

## WebRTC component configuration example:

Expand Down Expand Up @@ -164,6 +305,21 @@ shortcuts:

- **Camera not connecting?** Ensure IP is correct and phone application is not connected. Only one client can connect.
- **No video stream?** Sometimes camera doesn't start streaming. Reboot it.
- **Resolution shows as unknown?** The camera only reports its real video
parameters while it is streaming; an idle camera answers with an empty table.
Start the stream and the value fills in a couple of seconds later.
- **Resolution keeps reverting to HD?** Known limitation — set it while the
stream is running. See [Known issues](#known-issues).
- **Clock offset looks stale after pressing Sync time?** The value is re-read a
moment after the write. If that read-back doesn't land, the next info poll
replaces it with a genuine reading.
- **Missing sensors?** Most are conditional (see [Entities](#entities)), and
signal / SD usage / timezone are disabled by default — enable them
from the device page.
- **Talk-back does nothing?** The action now fails loudly with ffmpeg's own
error when the media can't be decoded. If it reports that the URL could not
be fetched, check that Home Assistant's internal URL is reachable from
itself, since the audio is pulled back over HTTP before being transcoded.

## Contributing

Expand Down
71 changes: 56 additions & 15 deletions custom_components/pppp_camera/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""The PPPP IP Camera integration."""

import select
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP,
Expand All @@ -15,17 +14,26 @@
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv
import voluptuous as vol
from aiopppp import NotConnectedError

from .camera import PPPPCamera
from .discovery import async_start_discovery
from .config_helpers import get_config
from .const import (
DOMAIN,
LOGGER,
PLATFORMS,
CONF_DEFAULTS,
CONF_IP,
CONF_DURATION,
CONF_INTERVAL,
CONF_LAMP,
CONF_IDLE_DISCONNECT_DELAY,
CONF_STATUS_POLL_INTERVAL,
CONF_INFO_POLL_INTERVAL,
DEFAULT_IDLE_DISCONNECT_DELAY,
DEFAULT_STATUS_POLL_INTERVAL,
DEFAULT_INFO_POLL_INTERVAL,
)


Expand Down Expand Up @@ -56,6 +64,18 @@
vol.Optional(CONF_IP): vol.Any(cv.string, [cv.string]),
}
),
vol.Optional(
CONF_IDLE_DISCONNECT_DELAY,
default=DEFAULT_IDLE_DISCONNECT_DELAY,
): vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.Optional(
CONF_STATUS_POLL_INTERVAL,
default=DEFAULT_STATUS_POLL_INTERVAL,
): vol.All(vol.Coerce(int), vol.Range(min=0)),
vol.Optional(
CONF_INFO_POLL_INTERVAL,
default=DEFAULT_INFO_POLL_INTERVAL,
): vol.All(vol.Coerce(int), vol.Range(min=0)),
}
)
},
Expand All @@ -81,6 +101,15 @@
# or single IP can also be specified (usually broadcast address)
ip: 192.168.1.255
# if 'ip' is not specified, discovery will listen on all interfaces
idle_disconnect_delay: 5 # seconds to keep a session warm after the last
# operation (0 = disconnect immediately)
status_poll_interval: 300 # seconds between battery/signal/SD refreshes
# (0 = never poll)
info_poll_interval: 3600 # seconds between clock/SSID refreshes
# (0 = never poll)

All of these can also be set per camera in the integration's options, which
takes precedence over the values here.
"""


Expand All @@ -89,9 +118,9 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool:
hass.data[DOMAIN] = {}

# load optional global registry config
if DOMAIN in config:
conf = config[DOMAIN]
hass.data[DOMAIN]["config"] = conf
cfg = config if DOMAIN in config else CONFIG_SCHEMA({DOMAIN: {}})
hass.data[DOMAIN]["config"] = cfg[DOMAIN]
LOGGER.debug("Config: %s", get_config(hass))

await async_start_discovery(hass)

Expand All @@ -105,10 +134,14 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
device = PPPPDevice(hass, config_entry)
try:
await device.async_setup()
except TimeoutError as err:
await device.device.close()
except (TimeoutError, NotConnectedError) as err:
# NotConnectedError is raised when the camera is found but the session is
# lost during connect (e.g. P2pRdy/handshake timeout) -- retry, don't fail.
# device.device may not exist yet if setup failed very early; guard it.
if getattr(device, "device", None) is not None:
await device.device.close()
raise ConfigEntryNotReady(
f"Could not connect to camera {device.device.ip_address}: {err}"
f"Could not connect to camera {device.host}: {err}"
) from err

hass.data[DOMAIN][config_entry.unique_id] = device
Expand All @@ -118,12 +151,14 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
Platform.BUTTON,
Platform.LIGHT,
Platform.SWITCH,
Platform.SENSOR,
Platform.SELECT,
]

await hass.config_entries.async_forward_entry_setups(config_entry, device.platforms)

# Reload entry when its updated.
config_entry.async_on_unload(config_entry.add_update_listener(async_reload_entry))
# PPPPDevice.async_setup() already registers an options-update listener that
# reloads the entry, so don't register a second one here (it would reload twice).
config_entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, device.async_stop)
)
Expand All @@ -132,9 +167,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
"""Reload the config entry when it changed."""
await hass.config_entries.async_reload(entry.entry_id)
device: PPPPDevice | None = hass.data.get(DOMAIN, {}).get(entry.unique_id)
# Unload the platforms that were actually set up (camera + lamp + button),
# not just PLATFORMS (camera only) -- otherwise the lamp/button entities are
# orphaned on unload/reload.
platforms = device.platforms if device and device.platforms else PLATFORMS
unloaded = await hass.config_entries.async_unload_platforms(entry, platforms)
if unloaded and device is not None:
# Tear the warm session down and drop the reference so nothing leaks
# across reloads.
await device.async_stop()
hass.data[DOMAIN].pop(entry.unique_id, None)
return unloaded
Binary file added custom_components/pppp_camera/brand/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added custom_components/pppp_camera/brand/icon@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading