Skip to content

Commit fcefe73

Browse files
committed
Release 1.0.10
1 parent 23b5ba5 commit fcefe73

8 files changed

Lines changed: 50 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## [1.0.10] (2022-12-04)
4+
### Added
5+
- Camera entity now supports snapshots and video streaming
6+
37
## [1.0.9] (2022-11-26)
48
### Added
59
- PTZ Support, exposed as `imou_life.ptz_location` and `imou_life.ptz_move` services

custom_components/imou_life/camera.py

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
from collections.abc import Callable
33
import logging
44

5-
from homeassistant.components.camera import ENTITY_ID_FORMAT, Camera
5+
from homeassistant.components.camera import (
6+
ENTITY_ID_FORMAT,
7+
Camera,
8+
CameraEntityFeature,
9+
)
610
from homeassistant.config_entries import ConfigEntry
711
from homeassistant.core import HomeAssistant
812
from homeassistant.helpers import entity_platform
@@ -16,6 +20,7 @@
1620
ATTR_PTZ_VERTICAL,
1721
ATTR_PTZ_ZOOM,
1822
DOMAIN,
23+
ENABLED_CAMERAS,
1924
SERVIZE_PTZ_LOCATION,
2025
SERVIZE_PTZ_MOVE,
2126
)
@@ -70,12 +75,35 @@ async def async_setup_entry(
7075
class ImouCamera(ImouEntity, Camera):
7176
"""imou camera class."""
7277

78+
_attr_supported_features = CameraEntityFeature.STREAM
79+
7380
def __init__(self, coordinator, config_entry, sensor_instance, entity_format):
7481
"""Initialize."""
82+
Camera.__init__(self)
7583
ImouEntity.__init__(
7684
self, coordinator, config_entry, sensor_instance, entity_format
7785
)
78-
Camera.__init__(self)
86+
87+
@property
88+
def entity_registry_enabled_default(self) -> bool:
89+
"""If the entity is enabled by default."""
90+
return self.sensor_instance.get_name() in ENABLED_CAMERAS
91+
92+
async def async_camera_image(self, width=None, height=None) -> bytes:
93+
"""Return bytes of camera image."""
94+
_LOGGER.debug(
95+
"[%s] requested camera image",
96+
self.device.get_name(),
97+
)
98+
return await self.sensor_instance.async_get_image()
99+
100+
async def stream_source(self) -> str:
101+
"""Return the source of the stream."""
102+
_LOGGER.debug(
103+
"[%s] requested camera stream url",
104+
self.device.get_name(),
105+
)
106+
return await self.sensor_instance.async_get_stream_url()
79107

80108
async def async_service_ptz_location(self, horizontal, vertical, zoom):
81109
"""Perform PTZ location action."""
@@ -104,7 +132,3 @@ async def async_service_ptz_move(self, operation, duration):
104132
operation,
105133
duration,
106134
)
107-
108-
async def async_camera_image(self, width=None, height=None):
109-
"""Return bytes of camera image."""
110-
return None

custom_components/imou_life/const.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@
4343
"pushNotifications",
4444
]
4545

46+
# cameras which are enabled by default
47+
ENABLED_CAMERAS = [
48+
"camera",
49+
]
50+
4651
# icons of the sensors
4752
SENSOR_ICONS = {
4853
"__default__": "mdi:bookmark",
@@ -74,4 +79,5 @@
7479
"siren": "mdi:alarm-light",
7580
# cameras
7681
"camera": "mdi:video",
82+
"cameraSD": "mdi:video",
7783
}

custom_components/imou_life/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"dependencies": [],
77
"config_flow": true,
88
"codeowners": ["@user2684"],
9-
"requirements": ["imouapi==1.0.9"],
10-
"version": "1.0.9",
9+
"requirements": ["imouapi==1.0.10"],
10+
"version": "1.0.10",
1111
"iot_class": "cloud_polling"
1212
}

requirements_test.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
-r requirements_dev.txt
22
pytest-homeassistant-custom-component==0.12.19
3-
imouapi==1.0.9
3+
imouapi==1.0.10

tests/test_config_flow.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def bypass_setup_fixture():
3737
yield
3838

3939

40+
@pytest.mark.asyncio
4041
async def test_discover_ok(hass, api_ok):
4142
"""Test discover flow: ok."""
4243
# Initialize a config flow as the user is clicking on add new integration
@@ -76,6 +77,7 @@ async def test_discover_ok(hass, api_ok):
7677
assert result["result"]
7778

7879

80+
@pytest.mark.asyncio
7981
async def test_login_error(hass, api_invalid_app_id):
8082
"""Test config flow: invalid app id."""
8183
result = await hass.config_entries.flow.async_init(
@@ -88,6 +90,7 @@ async def test_login_error(hass, api_invalid_app_id):
8890
assert result["errors"] == {"base": "invalid_configuration"}
8991

9092

93+
@pytest.mark.asyncio
9194
async def test_manual_ok(hass, api_ok):
9295
"""Test manual flow: ok."""
9396
# Initialize a config flow as the user is clicking on add new integration
@@ -128,6 +131,7 @@ async def test_manual_ok(hass, api_ok):
128131
assert result["result"]
129132

130133

134+
@pytest.mark.asyncio
131135
async def test_options_flow(hass):
132136
"""Test an options flow."""
133137
entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG_ENTRY, entry_id="test")

tests/test_init.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from .const import MOCK_CONFIG_ENTRY
1515

1616

17+
@pytest.mark.asyncio
1718
async def test_setup_unload_and_reload_entry(hass, api_ok):
1819
"""Test entry setup and unload."""
1920
# Create a mock entry so we don't have to go through config flow
@@ -39,6 +40,7 @@ async def test_setup_unload_and_reload_entry(hass, api_ok):
3940
assert config_entry.entry_id not in hass.data[DOMAIN]
4041

4142

43+
@pytest.mark.asyncio
4244
async def test_setup_entry_exception(hass, api_invalid_data):
4345
"""Test ConfigEntryNotReady when API raises an exception during entry setup."""
4446
config_entry = MockConfigEntry(

tests/test_switch.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ def bypass_added_to_hass():
2626
yield
2727

2828

29+
@pytest.mark.asyncio
2930
async def test_switch(hass, api_ok):
3031
"""Test switch services."""
3132
# Create a mock entry so we don't have to go through config flow

0 commit comments

Comments
 (0)