Exemple #1
0
async def test_camera_ws_update(hass: HomeAssistant, ufp: MockUFPFixture,
                                camera: ProtectCamera):
    """WS update updates camera entity."""

    await init_entry(hass, ufp, [camera])
    assert_entity_counts(hass, Platform.CAMERA, 2, 1)
    entity_id = "camera.test_camera_high"

    state = hass.states.get(entity_id)
    assert state and state.state == "idle"

    new_camera = camera.copy()
    new_camera.is_recording = True

    no_camera = camera.copy()
    no_camera.is_adopted = False

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera
    ufp.ws_msg(mock_msg)

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = no_camera
    ufp.ws_msg(mock_msg)

    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state and state.state == "recording"
Exemple #2
0
async def test_number_setup_camera_none(hass: HomeAssistant,
                                        mock_entry: MockEntityFixture,
                                        mock_camera: Camera):
    """Test number entity setup for camera devices (no features)."""

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.can_optical_zoom = False
    camera_obj.feature_flags.has_mic = False
    # has_wdr is an the inverse of has HDR
    camera_obj.feature_flags.has_hdr = True

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.NUMBER, 0, 0)
Exemple #3
0
async def test_number_setup_camera_missing_attr(hass: HomeAssistant,
                                                mock_entry: MockEntityFixture,
                                                mock_camera: Camera):
    """Test number entity setup for camera devices (no features, bad attrs)."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags = None

    Camera.__config__.validate_assignment = True

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.NUMBER, 0, 0)
Exemple #4
0
async def test_adopt(hass: HomeAssistant, ufp: MockUFPFixture,
                     camera: ProtectCamera):
    """Test setting up camera with no camera channels."""

    camera1 = camera.copy()
    camera1.channels = []

    await init_entry(hass, ufp, [camera1])
    assert_entity_counts(hass, Platform.CAMERA, 0, 0)

    await remove_entities(hass, ufp, [camera1])
    assert_entity_counts(hass, Platform.CAMERA, 0, 0)
    camera1.channels = []
    await adopt_devices(hass, ufp, [camera1])
    assert_entity_counts(hass, Platform.CAMERA, 0, 0)

    camera1.channels = camera.channels
    for channel in camera1.channels:
        channel._api = ufp.api

    mock_msg = Mock()
    mock_msg.changed_data = {"channels": camera.channels}
    mock_msg.new_obj = camera1
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()
    assert_entity_counts(hass, Platform.CAMERA, 2, 1)

    await remove_entities(hass, ufp, [camera1])
    assert_entity_counts(hass, Platform.CAMERA, 0, 0)
    await adopt_devices(hass, ufp, [camera1])
    assert_entity_counts(hass, Platform.CAMERA, 2, 1)
Exemple #5
0
async def test_select_update_doorbell_message(
    hass: HomeAssistant, ufp: MockUFPFixture, doorbell: Camera
):
    """Test select entity update (change doorbell message)."""

    await init_entry(hass, ufp, [doorbell])
    assert_entity_counts(hass, Platform.SELECT, 4, 4)

    _, entity_id = ids_from_device_description(
        Platform.SELECT, doorbell, CAMERA_SELECTS[2]
    )

    state = hass.states.get(entity_id)
    assert state
    assert state.state == "Default Message (Welcome)"

    new_camera = doorbell.copy()
    new_camera.lcd_message = LCDMessage(
        type=DoorbellMessageType.CUSTOM_MESSAGE, text="Test"
    )

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == "Test"
Exemple #6
0
async def camera_fixture(hass: HomeAssistant, mock_entry: MockEntityFixture,
                         mock_camera: Camera):
    """Fixture for a single camera for testing the media_player platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.has_speaker = True

    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.MEDIA_PLAYER, 1, 1)

    yield (camera_obj, "media_player.test_camera_speaker")

    Camera.__config__.validate_assignment = True
Exemple #7
0
async def camera_fixture(
    hass: HomeAssistant,
    mock_entry: MockEntityFixture,
    mock_camera: Camera,
    now: datetime,
):
    """Fixture for a single camera for testing the binary_sensor platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.has_chime = True
    camera_obj.last_ring = now - timedelta(hours=1)
    camera_obj.is_dark = False

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.nvr.system_info.storage.devices = []
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.BINARY_SENSOR, 2, 2)

    yield camera_obj

    Camera.__config__.validate_assignment = True
Exemple #8
0
async def camera_fixture(hass: HomeAssistant, mock_entry: MockEntityFixture,
                         mock_camera: Camera):
    """Fixture for a single camera for testing the number platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.can_optical_zoom = True
    camera_obj.feature_flags.has_mic = True
    # has_wdr is an the inverse of has HDR
    camera_obj.feature_flags.has_hdr = False
    camera_obj.isp_settings.wdr = 0
    camera_obj.mic_volume = 0
    camera_obj.isp_settings.zoom_position = 0

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.NUMBER, 3, 3)

    yield camera_obj

    Camera.__config__.validate_assignment = True
Exemple #9
0
async def camera_fixture(
    hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: Camera
):
    """Fixture for a single camera for testing the select platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.has_lcd_screen = True
    camera_obj.feature_flags.has_chime = True
    camera_obj.recording_settings.mode = RecordingMode.ALWAYS
    camera_obj.isp_settings.ir_led_mode = IRLEDMode.AUTO
    camera_obj.lcd_message = None
    camera_obj.chime_duration = 0

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.SELECT, 4, 4)

    yield camera_obj

    Camera.__config__.validate_assignment = True
Exemple #10
0
async def test_media_player_update(
    hass: HomeAssistant,
    ufp: MockUFPFixture,
    doorbell: Camera,
    unadopted_camera: Camera,
):
    """Test media_player entity update."""

    await init_entry(hass, ufp, [doorbell, unadopted_camera])
    assert_entity_counts(hass, Platform.MEDIA_PLAYER, 1, 1)

    new_camera = doorbell.copy()
    new_camera.talkback_stream = Mock()
    new_camera.talkback_stream.is_running = True

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get("media_player.test_camera_speaker")
    assert state
    assert state.state == STATE_PLAYING
Exemple #11
0
async def test_select_update_doorbell_message(
    hass: HomeAssistant,
    mock_entry: MockEntityFixture,
    camera: Camera,
):
    """Test select entity update (change doorbell message)."""

    _, entity_id = ids_from_device_description(
        Platform.SELECT, camera, CAMERA_SELECTS[2]
    )

    state = hass.states.get(entity_id)
    assert state
    assert state.state == "Default Message (Welcome)"

    new_bootstrap = copy(mock_entry.api.bootstrap)
    new_camera = camera.copy()
    new_camera.lcd_message = LCDMessage(
        type=DoorbellMessageType.CUSTOM_MESSAGE, text="Test"
    )

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    new_bootstrap.cameras = {new_camera.id: new_camera}
    mock_entry.api.bootstrap = new_bootstrap
    mock_entry.api.ws_subscription(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == "Test"
Exemple #12
0
def doorbell_fixture(camera: Camera, fixed_now: datetime):
    """Mock UniFi Protect Camera device (with chime)."""

    doorbell = camera.copy()
    doorbell.channels = [c.copy() for c in doorbell.channels]

    package_channel = doorbell.channels[0].copy()
    package_channel.name = "Package Camera"
    package_channel.id = 3
    package_channel.fps = 2
    package_channel.rtsp_alias = "test_package_alias"

    doorbell.channels.append(package_channel)
    doorbell.feature_flags.video_modes = [
        VideoMode.DEFAULT, VideoMode.HIGH_FPS
    ]
    doorbell.feature_flags.smart_detect_types = [
        SmartDetectObjectType.PERSON,
        SmartDetectObjectType.VEHICLE,
    ]
    doorbell.has_speaker = True
    doorbell.feature_flags.has_hdr = True
    doorbell.feature_flags.has_lcd_screen = True
    doorbell.feature_flags.has_speaker = True
    doorbell.feature_flags.has_privacy_mask = True
    doorbell.feature_flags.has_chime = True
    doorbell.feature_flags.has_smart_detect = True
    doorbell.feature_flags.has_package_camera = True
    doorbell.feature_flags.has_led_status = True
    doorbell.last_ring = fixed_now - timedelta(hours=1)
    return doorbell
Exemple #13
0
async def test_media_player_stop(
    hass: HomeAssistant,
    ufp: MockUFPFixture,
    doorbell: Camera,
    unadopted_camera: Camera,
):
    """Test media_player entity test media_stop."""

    await init_entry(hass, ufp, [doorbell, unadopted_camera])
    assert_entity_counts(hass, Platform.MEDIA_PLAYER, 1, 1)

    new_camera = doorbell.copy()
    new_camera.talkback_stream = AsyncMock()
    new_camera.talkback_stream.is_running = True

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    await hass.services.async_call(
        "media_player",
        "media_stop",
        {ATTR_ENTITY_ID: "media_player.test_camera_speaker"},
        blocking=True,
    )

    new_camera.talkback_stream.stop.assert_called_once()
Exemple #14
0
def unadopted_camera(camera: Camera):
    """Mock UniFi Protect Camera device (unadopted)."""

    no_camera = camera.copy()
    no_camera.channels = [c.copy() for c in no_camera.channels]
    no_camera.name = "Unadopted Camera"
    no_camera.is_adopted = False
    return no_camera
Exemple #15
0
async def test_switch_camera_privacy(hass: HomeAssistant, ufp: MockUFPFixture,
                                     doorbell: Camera):
    """Tests Privacy Mode switch for cameras with privacy mode defaulted on."""

    previous_mic = doorbell.mic_volume = 53
    previous_record = doorbell.recording_settings.mode = RecordingMode.DETECTIONS

    await init_entry(hass, ufp, [doorbell])
    assert_entity_counts(hass, Platform.SWITCH, 15, 14)

    description = PRIVACY_MODE_SWITCH

    doorbell.__fields__["set_privacy"] = Mock()
    doorbell.set_privacy = AsyncMock()

    _, entity_id = ids_from_device_description(Platform.SWITCH, doorbell,
                                               description)

    state = hass.states.get(entity_id)
    assert state and state.state == "off"
    assert ATTR_PREV_MIC not in state.attributes
    assert ATTR_PREV_RECORD not in state.attributes

    await hass.services.async_call("switch",
                                   "turn_on", {ATTR_ENTITY_ID: entity_id},
                                   blocking=True)

    doorbell.set_privacy.assert_called_with(True, 0, RecordingMode.NEVER)

    new_doorbell = doorbell.copy()
    new_doorbell.add_privacy_zone()
    new_doorbell.mic_volume = 0
    new_doorbell.recording_settings.mode = RecordingMode.NEVER
    ufp.api.bootstrap.cameras = {new_doorbell.id: new_doorbell}

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_doorbell
    ufp.ws_msg(mock_msg)

    state = hass.states.get(entity_id)
    assert state and state.state == "on"
    assert state.attributes[ATTR_PREV_MIC] == previous_mic
    assert state.attributes[ATTR_PREV_RECORD] == previous_record.value

    doorbell.set_privacy.reset_mock()

    await hass.services.async_call("switch",
                                   "turn_off", {ATTR_ENTITY_ID: entity_id},
                                   blocking=True)

    doorbell.set_privacy.assert_called_with(False, previous_mic,
                                            previous_record)
Exemple #16
0
async def test_set_chime_paired_doorbells(
    hass: HomeAssistant,
    ufp: MockUFPFixture,
    chime: Chime,
    doorbell: Camera,
):
    """Test set_chime_paired_doorbells."""

    ufp.api.update_device = AsyncMock()

    camera1 = doorbell.copy()
    camera1.name = "Test Camera 1"

    camera2 = doorbell.copy()
    camera2.name = "Test Camera 2"

    await init_entry(hass, ufp, [camera1, camera2, chime])

    registry = er.async_get(hass)
    chime_entry = registry.async_get("button.test_chime_play_chime")
    camera_entry = registry.async_get("binary_sensor.test_camera_2_doorbell")
    assert chime_entry is not None
    assert camera_entry is not None

    await hass.services.async_call(
        DOMAIN,
        SERVICE_SET_CHIME_PAIRED,
        {
            ATTR_DEVICE_ID: chime_entry.device_id,
            "doorbells": {
                ATTR_ENTITY_ID: ["binary_sensor.test_camera_1_doorbell"],
                ATTR_DEVICE_ID: [camera_entry.device_id],
            },
        },
        blocking=True,
    )

    ufp.api.update_device.assert_called_once_with(
        ModelType.CHIME, chime.id,
        {"cameraIds": sorted([camera1.id, camera2.id])})
Exemple #17
0
async def camera_fixture(hass: HomeAssistant, mock_entry: MockEntityFixture,
                         mock_camera: Camera):
    """Fixture for a single camera for testing the switch platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.recording_settings.mode = RecordingMode.DETECTIONS
    camera_obj.feature_flags.has_led_status = True
    camera_obj.feature_flags.has_hdr = True
    camera_obj.feature_flags.video_modes = [
        VideoMode.DEFAULT, VideoMode.HIGH_FPS
    ]
    camera_obj.feature_flags.has_privacy_mask = True
    camera_obj.feature_flags.has_speaker = True
    camera_obj.feature_flags.has_smart_detect = True
    camera_obj.feature_flags.smart_detect_types = [
        SmartDetectObjectType.PERSON,
        SmartDetectObjectType.VEHICLE,
    ]
    camera_obj.is_ssh_enabled = False
    camera_obj.led_settings.is_enabled = False
    camera_obj.hdr_mode = False
    camera_obj.video_mode = VideoMode.DEFAULT
    camera_obj.remove_privacy_zone()
    camera_obj.speaker_settings.are_system_sounds_enabled = False
    camera_obj.osd_settings.is_name_enabled = False
    camera_obj.osd_settings.is_date_enabled = False
    camera_obj.osd_settings.is_logo_enabled = False
    camera_obj.osd_settings.is_debug_enabled = False
    camera_obj.smart_detect_settings.object_types = []

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.SWITCH, 12, 11)

    yield camera_obj

    Camera.__config__.validate_assignment = True
Exemple #18
0
async def test_binary_sensor_update_doorbell(
    hass: HomeAssistant,
    mock_entry: MockEntityFixture,
    camera: Camera,
):
    """Test select entity update (change doorbell message)."""

    _, entity_id = ids_from_device_description(Platform.BINARY_SENSOR, camera,
                                               CAMERA_SENSORS[0])

    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_OFF

    new_bootstrap = copy(mock_entry.api.bootstrap)
    new_camera = camera.copy()
    new_camera.last_ring = utcnow()

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    new_bootstrap.cameras = {new_camera.id: new_camera}
    mock_entry.api.bootstrap = new_bootstrap
    mock_entry.api.ws_subscription(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_ON

    # fire event a second time for code coverage (cancel existing)
    mock_entry.api.ws_subscription(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_ON

    # since time is not really changing, switch the last ring back to allow turn off
    new_camera.last_ring = utcnow() - RING_INTERVAL
    await time_changed(hass, RING_INTERVAL.total_seconds())
    await hass.async_block_till_done()
    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_OFF
Exemple #19
0
async def test_missing_channels(
    hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: ProtectCamera
):
    """Test setting up camera with no camera channels."""

    camera = mock_camera.copy(deep=True)
    camera.channels = []

    mock_entry.api.bootstrap.cameras = {camera.id: camera}

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    entity_registry = er.async_get(hass)

    assert len(hass.states.async_all()) == 0
    assert len(entity_registry.entities) == 0
Exemple #20
0
async def test_binary_sensor_update_motion(
    hass: HomeAssistant,
    ufp: MockUFPFixture,
    doorbell: Camera,
    unadopted_camera: Camera,
    fixed_now: datetime,
):
    """Test binary_sensor motion entity."""

    await init_entry(hass, ufp, [doorbell, unadopted_camera])
    assert_entity_counts(hass, Platform.BINARY_SENSOR, 9, 9)

    _, entity_id = ids_from_device_description(
        Platform.BINARY_SENSOR, doorbell, MOTION_SENSORS[0]
    )

    event = Event(
        id="test_event_id",
        type=EventType.MOTION,
        start=fixed_now - timedelta(seconds=1),
        end=None,
        score=100,
        smart_detect_types=[],
        smart_detect_event_ids=[],
        camera_id=doorbell.id,
    )

    new_camera = doorbell.copy()
    new_camera.is_motion_detected = True
    new_camera.last_motion_event_id = event.id

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.api.bootstrap.events = {event.id: event}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_ON
    assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
    assert state.attributes[ATTR_EVENT_SCORE] == 100
Exemple #21
0
async def camera_fixture(
    hass: HomeAssistant,
    mock_entry: MockEntityFixture,
    mock_camera: Camera,
    now: datetime,
):
    """Fixture for a single camera for testing the sensor platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.feature_flags.has_smart_detect = True
    camera_obj.is_smart_detected = False
    camera_obj.wired_connection_state = WiredConnectionState(phy_rate=1000)
    camera_obj.wifi_connection_state = WifiConnectionState(signal_quality=100,
                                                           signal_strength=-50)
    camera_obj.stats.rx_bytes = 100.0
    camera_obj.stats.tx_bytes = 100.0
    camera_obj.stats.video.recording_start = now
    camera_obj.stats.storage.used = 100.0
    camera_obj.stats.storage.used = 100.0
    camera_obj.stats.storage.rate = 100.0
    camera_obj.voltage = 20.0

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.nvr.system_info.storage.devices = []
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    # 3 from all, 6 from camera, 12 NVR
    assert_entity_counts(hass, Platform.SENSOR, 22, 14)

    yield camera_obj

    Camera.__config__.validate_assignment = True
Exemple #22
0
def camera_all_fixture(camera: Camera):
    """Mock UniFi Protect Camera device."""

    all_camera = camera.copy()
    all_camera.channels = [all_camera.channels[0].copy()]

    medium_channel = all_camera.channels[0].copy()
    medium_channel.name = "Medium"
    medium_channel.id = 1
    medium_channel.rtsp_alias = "test_medium_alias"
    all_camera.channels.append(medium_channel)

    low_channel = all_camera.channels[0].copy()
    low_channel.name = "Low"
    low_channel.id = 2
    low_channel.rtsp_alias = "test_medium_alias"
    all_camera.channels.append(low_channel)

    return all_camera
Exemple #23
0
async def test_sensor_update_motion(
    hass: HomeAssistant, mock_entry: MockEntityFixture, camera: Camera, now: datetime
):
    """Test sensor motion entity."""
    # 3 from all, 7 from camera, 12 NVR
    assert_entity_counts(hass, Platform.SENSOR, 24, 13)

    _, entity_id = ids_from_device_description(
        Platform.SENSOR, camera, MOTION_SENSORS[0]
    )

    event = Event(
        id="test_event_id",
        type=EventType.SMART_DETECT,
        start=now - timedelta(seconds=1),
        end=None,
        score=100,
        smart_detect_types=[SmartDetectObjectType.PERSON],
        smart_detect_event_ids=[],
        camera_id=camera.id,
        api=mock_entry.api,
    )

    new_bootstrap = copy(mock_entry.api.bootstrap)
    new_camera = camera.copy()
    new_camera.is_smart_detected = True
    new_camera.last_smart_detect_event_id = event.id

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = event

    new_bootstrap.cameras = {new_camera.id: new_camera}
    new_bootstrap.events = {event.id: event}
    mock_entry.api.bootstrap = new_bootstrap
    mock_entry.api.ws_subscription(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == SmartDetectObjectType.PERSON.value
    assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
    assert state.attributes[ATTR_EVENT_SCORE] == 100
Exemple #24
0
async def test_camera_interval_update(hass: HomeAssistant, ufp: MockUFPFixture,
                                      camera: ProtectCamera):
    """Interval updates updates camera entity."""

    await init_entry(hass, ufp, [camera])
    assert_entity_counts(hass, Platform.CAMERA, 2, 1)
    entity_id = "camera.test_camera_high"

    state = hass.states.get(entity_id)
    assert state and state.state == "idle"

    new_camera = camera.copy()
    new_camera.is_recording = True

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.api.update = AsyncMock(return_value=ufp.api.bootstrap)
    await time_changed(hass, DEFAULT_SCAN_INTERVAL)

    state = hass.states.get(entity_id)
    assert state and state.state == "recording"
Exemple #25
0
async def camera_privacy_fixture(hass: HomeAssistant,
                                 mock_entry: MockEntityFixture,
                                 mock_camera: Camera):
    """Fixture for a single camera for testing the switch platform."""

    # disable pydantic validation so mocking can happen
    Camera.__config__.validate_assignment = False

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"
    camera_obj.recording_settings.mode = RecordingMode.NEVER
    camera_obj.feature_flags.has_led_status = False
    camera_obj.feature_flags.has_hdr = False
    camera_obj.feature_flags.video_modes = [VideoMode.DEFAULT]
    camera_obj.feature_flags.has_privacy_mask = True
    camera_obj.feature_flags.has_speaker = False
    camera_obj.feature_flags.has_smart_detect = False
    camera_obj.add_privacy_zone()
    camera_obj.is_ssh_enabled = False
    camera_obj.osd_settings.is_name_enabled = False
    camera_obj.osd_settings.is_date_enabled = False
    camera_obj.osd_settings.is_logo_enabled = False
    camera_obj.osd_settings.is_debug_enabled = False

    mock_entry.api.bootstrap.reset_objects()
    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.SWITCH, 6, 5)

    yield camera_obj

    Camera.__config__.validate_assignment = True
async def camera_fixture(hass: HomeAssistant, mock_entry: MockEntityFixture,
                         mock_camera: Camera):
    """Fixture for a single camera for testing the button platform."""

    camera_obj = mock_camera.copy(deep=True)
    camera_obj._api = mock_entry.api
    camera_obj.channels[0]._api = mock_entry.api
    camera_obj.channels[1]._api = mock_entry.api
    camera_obj.channels[2]._api = mock_entry.api
    camera_obj.name = "Test Camera"

    mock_entry.api.bootstrap.cameras = {
        camera_obj.id: camera_obj,
    }

    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.BUTTON, 1, 0)

    return (camera_obj, "button.test_camera_reboot_device")
Exemple #27
0
async def test_camera_ws_update_offline(hass: HomeAssistant,
                                        ufp: MockUFPFixture,
                                        camera: ProtectCamera):
    """WS updates marks camera unavailable."""

    await init_entry(hass, ufp, [camera])
    assert_entity_counts(hass, Platform.CAMERA, 2, 1)
    entity_id = "camera.test_camera_high"

    state = hass.states.get(entity_id)
    assert state and state.state == "idle"

    # camera goes offline
    new_camera = camera.copy()
    new_camera.state = StateType.DISCONNECTED

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state and state.state == "unavailable"

    # camera comes back online
    new_camera.state = StateType.CONNECTED

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    ufp.api.bootstrap.cameras = {new_camera.id: new_camera}
    ufp.ws_msg(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state and state.state == "idle"
Exemple #28
0
async def test_binary_sensor_update_motion(hass: HomeAssistant,
                                           mock_entry: MockEntityFixture,
                                           camera: Camera, now: datetime):
    """Test binary_sensor motion entity."""

    _, entity_id = ids_from_device_description(Platform.BINARY_SENSOR, camera,
                                               MOTION_SENSORS[0])

    event = Event(
        id="test_event_id",
        type=EventType.MOTION,
        start=now - timedelta(seconds=1),
        end=None,
        score=100,
        smart_detect_types=[],
        smart_detect_event_ids=[],
        camera_id=camera.id,
    )

    new_bootstrap = copy(mock_entry.api.bootstrap)
    new_camera = camera.copy()
    new_camera.is_motion_detected = True
    new_camera.last_motion_event_id = event.id

    mock_msg = Mock()
    mock_msg.changed_data = {}
    mock_msg.new_obj = new_camera

    new_bootstrap.cameras = {new_camera.id: new_camera}
    new_bootstrap.events = {event.id: event}
    mock_entry.api.bootstrap = new_bootstrap
    mock_entry.api.ws_subscription(mock_msg)
    await hass.async_block_till_done()

    state = hass.states.get(entity_id)
    assert state
    assert state.state == STATE_ON
    assert state.attributes[ATTR_ATTRIBUTION] == DEFAULT_ATTRIBUTION
    assert state.attributes[ATTR_EVENT_SCORE] == 100
Exemple #29
0
async def test_basic_setup(
    hass: HomeAssistant, mock_entry: MockEntityFixture, mock_camera: ProtectCamera
):
    """Test working setup of unifiprotect entry."""

    camera_high_only = mock_camera.copy(deep=True)
    camera_high_only._api = mock_entry.api
    camera_high_only.channels[0]._api = mock_entry.api
    camera_high_only.channels[1]._api = mock_entry.api
    camera_high_only.channels[2]._api = mock_entry.api
    camera_high_only.name = "Test Camera 1"
    camera_high_only.id = "test_high"
    camera_high_only.channels[0].is_rtsp_enabled = True
    camera_high_only.channels[0].name = "High"
    camera_high_only.channels[0].rtsp_alias = "test_high_alias"
    camera_high_only.channels[1].is_rtsp_enabled = False
    camera_high_only.channels[2].is_rtsp_enabled = False

    camera_medium_only = mock_camera.copy(deep=True)
    camera_medium_only._api = mock_entry.api
    camera_medium_only.channels[0]._api = mock_entry.api
    camera_medium_only.channels[1]._api = mock_entry.api
    camera_medium_only.channels[2]._api = mock_entry.api
    camera_medium_only.name = "Test Camera 2"
    camera_medium_only.id = "test_medium"
    camera_medium_only.channels[0].is_rtsp_enabled = False
    camera_medium_only.channels[1].is_rtsp_enabled = True
    camera_medium_only.channels[1].name = "Medium"
    camera_medium_only.channels[1].rtsp_alias = "test_medium_alias"
    camera_medium_only.channels[2].is_rtsp_enabled = False

    camera_all_channels = mock_camera.copy(deep=True)
    camera_all_channels._api = mock_entry.api
    camera_all_channels.channels[0]._api = mock_entry.api
    camera_all_channels.channels[1]._api = mock_entry.api
    camera_all_channels.channels[2]._api = mock_entry.api
    camera_all_channels.name = "Test Camera 3"
    camera_all_channels.id = "test_all"
    camera_all_channels.channels[0].is_rtsp_enabled = True
    camera_all_channels.channels[0].name = "High"
    camera_all_channels.channels[0].rtsp_alias = "test_high_alias"
    camera_all_channels.channels[1].is_rtsp_enabled = True
    camera_all_channels.channels[1].name = "Medium"
    camera_all_channels.channels[1].rtsp_alias = "test_medium_alias"
    camera_all_channels.channels[2].is_rtsp_enabled = True
    camera_all_channels.channels[2].name = "Low"
    camera_all_channels.channels[2].rtsp_alias = "test_low_alias"

    camera_no_channels = mock_camera.copy(deep=True)
    camera_no_channels._api = mock_entry.api
    camera_no_channels.channels[0]._api = mock_entry.api
    camera_no_channels.channels[1]._api = mock_entry.api
    camera_no_channels.channels[2]._api = mock_entry.api
    camera_no_channels.name = "Test Camera 4"
    camera_no_channels.id = "test_none"
    camera_no_channels.channels[0].is_rtsp_enabled = False
    camera_no_channels.channels[0].name = "High"
    camera_no_channels.channels[1].is_rtsp_enabled = False
    camera_no_channels.channels[2].is_rtsp_enabled = False

    camera_package = mock_camera.copy(deep=True)
    camera_package._api = mock_entry.api
    camera_package.channels[0]._api = mock_entry.api
    camera_package.channels[1]._api = mock_entry.api
    camera_package.channels[2]._api = mock_entry.api
    camera_package.name = "Test Camera 5"
    camera_package.id = "test_package"
    camera_package.channels[0].is_rtsp_enabled = True
    camera_package.channels[0].name = "High"
    camera_package.channels[0].rtsp_alias = "test_high_alias"
    camera_package.channels[1].is_rtsp_enabled = False
    camera_package.channels[2].is_rtsp_enabled = False
    package_channel = camera_package.channels[0].copy(deep=True)
    package_channel.is_rtsp_enabled = False
    package_channel.name = "Package Camera"
    package_channel.id = 3
    package_channel.fps = 2
    package_channel.rtsp_alias = "test_package_alias"
    camera_package.channels.append(package_channel)

    mock_entry.api.bootstrap.cameras = {
        camera_high_only.id: camera_high_only,
        camera_medium_only.id: camera_medium_only,
        camera_all_channels.id: camera_all_channels,
        camera_no_channels.id: camera_no_channels,
        camera_package.id: camera_package,
    }
    await hass.config_entries.async_setup(mock_entry.entry.entry_id)
    await hass.async_block_till_done()

    assert_entity_counts(hass, Platform.CAMERA, 14, 6)

    # test camera 1
    entity_id = validate_default_camera_entity(hass, camera_high_only, 0)
    await validate_rtsps_camera_state(hass, camera_high_only, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_high_only, 0)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_high_only, 0, entity_id)

    # test camera 2
    entity_id = validate_default_camera_entity(hass, camera_medium_only, 1)
    await validate_rtsps_camera_state(hass, camera_medium_only, 1, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_medium_only, 1)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_medium_only, 1, entity_id)

    # test camera 3
    entity_id = validate_default_camera_entity(hass, camera_all_channels, 0)
    await validate_rtsps_camera_state(hass, camera_all_channels, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all_channels, 0)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all_channels, 0, entity_id)

    entity_id = validate_rtsps_camera_entity(hass, camera_all_channels, 1)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsps_camera_state(hass, camera_all_channels, 1, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all_channels, 1)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all_channels, 1, entity_id)

    entity_id = validate_rtsps_camera_entity(hass, camera_all_channels, 2)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsps_camera_state(hass, camera_all_channels, 2, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all_channels, 2)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all_channels, 2, entity_id)

    # test camera 4
    entity_id = validate_default_camera_entity(hass, camera_no_channels, 0)
    await validate_no_stream_camera_state(
        hass, camera_no_channels, 0, entity_id, features=0
    )

    # test camera 5
    entity_id = validate_default_camera_entity(hass, camera_package, 0)
    await validate_rtsps_camera_state(hass, camera_package, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_package, 0)
    await enable_entity(hass, mock_entry.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_package, 0, entity_id)

    entity_id = validate_default_camera_entity(hass, camera_package, 3)
    await validate_no_stream_camera_state(
        hass, camera_package, 3, entity_id, features=0
    )
Exemple #30
0
async def test_basic_setup(
    hass: HomeAssistant,
    ufp: MockUFPFixture,
    camera_all: ProtectCamera,
    doorbell: ProtectCamera,
):
    """Test working setup of unifiprotect entry."""

    camera_high_only = camera_all.copy()
    camera_high_only.channels = [c.copy() for c in camera_all.channels]
    camera_high_only.name = "Test Camera 1"
    camera_high_only.channels[0].is_rtsp_enabled = True
    camera_high_only.channels[1].is_rtsp_enabled = False
    camera_high_only.channels[2].is_rtsp_enabled = False

    camera_medium_only = camera_all.copy()
    camera_medium_only.channels = [c.copy() for c in camera_all.channels]
    camera_medium_only.name = "Test Camera 2"
    camera_medium_only.channels[0].is_rtsp_enabled = False
    camera_medium_only.channels[1].is_rtsp_enabled = True
    camera_medium_only.channels[2].is_rtsp_enabled = False

    camera_all.name = "Test Camera 3"

    camera_no_channels = camera_all.copy()
    camera_no_channels.channels = [c.copy() for c in camera_all.channels]
    camera_no_channels.name = "Test Camera 4"
    camera_no_channels.channels[0].is_rtsp_enabled = False
    camera_no_channels.channels[1].is_rtsp_enabled = False
    camera_no_channels.channels[2].is_rtsp_enabled = False

    doorbell.name = "Test Camera 5"

    devices = [
        camera_high_only,
        camera_medium_only,
        camera_all,
        camera_no_channels,
        doorbell,
    ]
    await init_entry(hass, ufp, devices)

    assert_entity_counts(hass, Platform.CAMERA, 14, 6)

    # test camera 1
    entity_id = validate_default_camera_entity(hass, camera_high_only, 0)
    await validate_rtsps_camera_state(hass, camera_high_only, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_high_only, 0)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_high_only, 0, entity_id)

    # test camera 2
    entity_id = validate_default_camera_entity(hass, camera_medium_only, 1)
    await validate_rtsps_camera_state(hass, camera_medium_only, 1, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_medium_only, 1)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_medium_only, 1, entity_id)

    # test camera 3
    entity_id = validate_default_camera_entity(hass, camera_all, 0)
    await validate_rtsps_camera_state(hass, camera_all, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all, 0)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all, 0, entity_id)

    entity_id = validate_rtsps_camera_entity(hass, camera_all, 1)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsps_camera_state(hass, camera_all, 1, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all, 1)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all, 1, entity_id)

    entity_id = validate_rtsps_camera_entity(hass, camera_all, 2)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsps_camera_state(hass, camera_all, 2, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, camera_all, 2)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, camera_all, 2, entity_id)

    # test camera 4
    entity_id = validate_default_camera_entity(hass, camera_no_channels, 0)
    await validate_no_stream_camera_state(hass,
                                          camera_no_channels,
                                          0,
                                          entity_id,
                                          features=0)

    # test camera 5
    entity_id = validate_default_camera_entity(hass, doorbell, 0)
    await validate_rtsps_camera_state(hass, doorbell, 0, entity_id)

    entity_id = validate_rtsp_camera_entity(hass, doorbell, 0)
    await enable_entity(hass, ufp.entry.entry_id, entity_id)
    await validate_rtsp_camera_state(hass, doorbell, 0, entity_id)

    entity_id = validate_default_camera_entity(hass, doorbell, 3)
    await validate_no_stream_camera_state(hass,
                                          doorbell,
                                          3,
                                          entity_id,
                                          features=0)