-
-
Notifications
You must be signed in to change notification settings - Fork 37.5k
Add QVR Pro integration #31173
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Add QVR Pro integration #31173
Changes from all commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
b5b509d
Initial working commit
oblogic7 9107f4c
Create const file. Load camera from component.
oblogic7 04427a9
Handle failed authentication. Bump library version.
oblogic7 74b39c4
Remove line break
oblogic7 37cd298
Camera attributes and recording services
oblogic7 e88efcc
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
oblogic7 d2fe4f6
Add services, manifest, constant update, and exclude_channels. Prefi…
oblogic7 af19a6e
Update codeowners
oblogic7 3e52766
Update coveragerc
oblogic7 c70fc28
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
oblogic7 a003f5c
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
oblogic7 f30e36a
Remove codeowners line
oblogic7 d8bc8dc
Update codeowners again from python3 -m script.hassfest
oblogic7 79e2b44
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
oblogic7 0202d8a
Update homeassistant/components/qvrpro/__init__.py
oblogic7 99d067c
Requested changes
oblogic7 15e278c
Merge branch 'qvrpro' of https://github.com/oblogic7/home-assistant i…
oblogic7 d337632
Fix typo
oblogic7 1bbd804
Update to use exception. Bump library version.
oblogic7 d5bc4e8
Support stream component
oblogic7 f2e26ed
Merge branch 'qvrpro' of https://github.com/oblogic7/home-assistant i…
oblogic7 ede446b
Update module header
oblogic7 bdb7b94
Missing property wrapper
oblogic7 4accc26
Partial requested changes
oblogic7 3b3f65b
Update coveragerc and codeowners
oblogic7 c1da03b
Move constants to const file. Add SHORT_NAME
oblogic7 366f535
Add conf variable
oblogic7 90a27e9
Use camera domain
oblogic7 bb63e68
More requested changes
oblogic7 6f887ca
Requested changes
oblogic7 a0f1d29
Requested changes
oblogic7 33bb74d
Merge remote-tracking branch 'upstream/dev' into qvrpro
oblogic7 0d476b1
Update prefix
oblogic7 afe1929
Handle error condition when camera is not configured to support live …
oblogic7 31e5fc2
Move method to camera setup. Disable stream component support.
oblogic7 e072e6d
Merge branch 'dev' of https://github.com/home-assistant/home-assistan…
oblogic7 e7ee71e
Move auth string to library to prevent private member access
oblogic7 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
| """Support for QVR Pro NVR software by QNAP.""" | ||
|
|
||
| import logging | ||
|
|
||
| from pyqvrpro import Client | ||
| from pyqvrpro.client import AuthenticationError, InsufficientPermissionsError | ||
| import voluptuous as vol | ||
|
|
||
| from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN | ||
| from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME | ||
| import homeassistant.helpers.config_validation as cv | ||
| from homeassistant.helpers.discovery import load_platform | ||
|
|
||
| from .const import ( | ||
| CONF_EXCLUDE_CHANNELS, | ||
| DOMAIN, | ||
| SERVICE_START_RECORD, | ||
| SERVICE_STOP_RECORD, | ||
| ) | ||
|
|
||
| SERVICE_CHANNEL_GUID = "guid" | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
| CONFIG_SCHEMA = vol.Schema( | ||
| { | ||
| DOMAIN: vol.Schema( | ||
| { | ||
| vol.Required(CONF_HOST): cv.string, | ||
| vol.Required(CONF_USERNAME): cv.string, | ||
| vol.Required(CONF_PASSWORD): cv.string, | ||
| vol.Optional(CONF_EXCLUDE_CHANNELS, default=[]): vol.All( | ||
| cv.ensure_list_csv, [cv.positive_int] | ||
| ), | ||
| } | ||
| ) | ||
| }, | ||
| extra=vol.ALLOW_EXTRA, | ||
| ) | ||
|
|
||
| SERVICE_CHANNEL_RECORD_SCHEMA = vol.Schema( | ||
| {vol.Required(SERVICE_CHANNEL_GUID): cv.string} | ||
| ) | ||
|
|
||
|
|
||
| def setup(hass, config): | ||
| """Set up the QVR Pro component.""" | ||
| conf = config[DOMAIN] | ||
| user = conf[CONF_USERNAME] | ||
| password = conf[CONF_PASSWORD] | ||
| host = conf[CONF_HOST] | ||
| excluded_channels = conf[CONF_EXCLUDE_CHANNELS] | ||
|
|
||
| try: | ||
| qvrpro = Client(user, password, host) | ||
|
|
||
| channel_resp = qvrpro.get_channel_list() | ||
|
|
||
| except InsufficientPermissionsError: | ||
| _LOGGER.error("User must have Surveillance Management permission") | ||
| return False | ||
| except AuthenticationError: | ||
| _LOGGER.error("Authentication failed") | ||
| return False | ||
|
|
||
| channels = [] | ||
|
|
||
| for channel in channel_resp["channels"]: | ||
| if channel["channel_index"] + 1 in excluded_channels: | ||
| continue | ||
|
|
||
| channels.append(channel) | ||
|
|
||
| hass.data[DOMAIN] = {"channels": channels, "client": qvrpro} | ||
|
|
||
| load_platform(hass, CAMERA_DOMAIN, DOMAIN, {}, config) | ||
|
|
||
| # Register services | ||
| def handle_start_record(call): | ||
| guid = call.data[SERVICE_CHANNEL_GUID] | ||
| qvrpro.start_recording(guid) | ||
|
|
||
| def handle_stop_record(call): | ||
| guid = call.data[SERVICE_CHANNEL_GUID] | ||
| qvrpro.stop_recording(guid) | ||
|
|
||
| hass.services.register( | ||
| DOMAIN, | ||
| SERVICE_START_RECORD, | ||
| handle_start_record, | ||
| schema=SERVICE_CHANNEL_RECORD_SCHEMA, | ||
| ) | ||
| hass.services.register( | ||
| DOMAIN, | ||
| SERVICE_STOP_RECORD, | ||
| handle_stop_record, | ||
| schema=SERVICE_CHANNEL_RECORD_SCHEMA, | ||
| ) | ||
|
|
||
| return True |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| """Support for QVR Pro streams.""" | ||
|
|
||
| import logging | ||
|
|
||
| from pyqvrpro.client import QVRResponseError | ||
|
|
||
| from homeassistant.components.camera import Camera | ||
|
|
||
| from .const import DOMAIN, SHORT_NAME | ||
|
|
||
| _LOGGER = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| def setup_platform(hass, config, add_entities, discovery_info=None): | ||
| """Set up the QVR Pro camera platform.""" | ||
| if discovery_info is None: | ||
| return | ||
|
|
||
| client = hass.data[DOMAIN]["client"] | ||
|
|
||
| entities = [] | ||
|
|
||
| for channel in hass.data[DOMAIN]["channels"]: | ||
|
|
||
| stream_source = get_stream_source(channel["guid"], client) | ||
| entities.append( | ||
| QVRProCamera(**channel, stream_source=stream_source, client=client) | ||
| ) | ||
|
|
||
| add_entities(entities) | ||
|
|
||
|
|
||
| def get_stream_source(guid, client): | ||
| """Get channel stream source.""" | ||
| try: | ||
| resp = client.get_channel_live_stream(guid, protocol="rtsp") | ||
|
|
||
| full_url = resp["resourceUris"] | ||
|
|
||
| protocol = full_url[:7] | ||
| auth = f"{client.get_auth_string()}@" | ||
| url = full_url[7:] | ||
|
|
||
| return f"{protocol}{auth}{url}" | ||
|
|
||
| except QVRResponseError as ex: | ||
| _LOGGER.error(ex) | ||
| return None | ||
|
|
||
|
|
||
| class QVRProCamera(Camera): | ||
| """Representation of a QVR Pro camera.""" | ||
|
|
||
| def __init__(self, name, model, brand, channel_index, guid, stream_source, client): | ||
| """Init QVR Pro camera.""" | ||
|
|
||
| self._name = f"{SHORT_NAME} {name}" | ||
| self._model = model | ||
| self._brand = brand | ||
| self.index = channel_index | ||
| self.guid = guid | ||
| self._client = client | ||
| self._stream_source = stream_source | ||
|
|
||
| self._supported_features = 0 | ||
|
|
||
| super().__init__() | ||
|
|
||
| @property | ||
| def name(self): | ||
| """Return the name of the entity.""" | ||
| return self._name | ||
|
|
||
| @property | ||
| def model(self): | ||
| """Return the model of the entity.""" | ||
| return self._model | ||
|
|
||
| @property | ||
| def brand(self): | ||
| """Return the brand of the entity.""" | ||
| return self._brand | ||
|
|
||
| @property | ||
| def device_state_attributes(self): | ||
| """Get the state attributes.""" | ||
| attrs = {"qvr_guid": self.guid} | ||
|
|
||
| return attrs | ||
|
|
||
| def camera_image(self): | ||
| """Get image bytes from camera.""" | ||
| return self._client.get_snapshot(self.guid) | ||
|
|
||
| async def stream_source(self): | ||
| """Get stream source.""" | ||
| return self._stream_source | ||
|
|
||
| @property | ||
| def supported_features(self): | ||
| """Get supported features.""" | ||
| return self._supported_features | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| """Constants for QVR Pro component.""" | ||
|
|
||
| DOMAIN = "qvr_pro" | ||
| SHORT_NAME = "QVR" | ||
|
|
||
| CONF_EXCLUDE_CHANNELS = "exclude_channels" | ||
|
|
||
| SERVICE_STOP_RECORD = "stop_record" | ||
| SERVICE_START_RECORD = "start_record" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| { | ||
| "domain": "qvr_pro", | ||
| "name": "QVR Pro", | ||
| "documentation": "https://www.home-assistant.io/integrations/qvr_pro", | ||
| "requirements": ["pyqvrpro==0.51"], | ||
| "dependencies": [], | ||
| "codeowners": ["@oblogic7"] | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| start_record: | ||
| description: Start QVR Pro recording on specified channel. | ||
| fields: | ||
| guid: | ||
| description: GUID of the channel to start recording. | ||
| example: '245EBE933C0A597EBE865C0A245E0002' | ||
|
|
||
| stop_record: | ||
| description: Stop QVR Pro recording on specified channel. | ||
| fields: | ||
| guid: | ||
| description: GUID of the channel to stop recording. | ||
| example: '245EBE933C0A597EBE865C0A245E0002' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.