Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.

Commit d002c84

Browse files
authored
Merge pull request #17 from fwestenberg/v0013
Version fix and stream values
2 parents 1bc07d3 + df7e5db commit d002c84

2 files changed

Lines changed: 66 additions & 36 deletions

File tree

reolink/camera_api.py

Lines changed: 64 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,20 @@
1818
_LOGGER = logging.getLogger(__name__)
1919

2020

21-
class Api: #pylint: disable=too-many-instance-attributes disable=too-many-public-methods
21+
class Api: # pylint: disable=too-many-instance-attributes disable=too-many-public-methods
2222
"""Reolink API class."""
2323

24-
def __init__(self, host, port, username, password, channel=DEFAULT_CHANNEL, timeout=DEFAULT_TIMEOUT):
24+
def __init__(
25+
self,
26+
host,
27+
port,
28+
username,
29+
password,
30+
channel=DEFAULT_CHANNEL,
31+
protocol=DEFAULT_PROTOCOL,
32+
stream=DEFAULT_STREAM,
33+
timeout=DEFAULT_TIMEOUT,
34+
):
2535
"""Initialize the API class."""
2636
self._url = f"http://{host}:{port}/cgi-bin/api.cgi"
2737
self._host = host
@@ -115,7 +125,7 @@ def model(self):
115125
def manufacturer(self):
116126
"""Return the manufacturer name (Reolink)."""
117127
return MANUFACTURER
118-
128+
119129
@property
120130
def channels(self):
121131
"""Return the number of channels."""
@@ -294,7 +304,9 @@ async def get_states(self, cmd_list=None):
294304
await self.map_json_response(json_data)
295305
return True
296306
except (TypeError, json.JSONDecodeError):
297-
_LOGGER.debug("Host: %s: Error translating Reolink state response", self._host)
307+
_LOGGER.debug(
308+
"Host: %s: Error translating Reolink state response", self._host
309+
)
298310
await self.clear_token()
299311
return False
300312

@@ -322,7 +334,9 @@ async def get_settings(self):
322334
await self.map_json_response(json_data)
323335
return True
324336
except (TypeError, json.JSONDecodeError):
325-
_LOGGER.debug("Host %s: Error translating Reolink settings response", self._host)
337+
_LOGGER.debug(
338+
"Host %s: Error translating Reolink settings response", self._host
339+
)
326340
await self.clear_token()
327341
return False
328342

@@ -339,8 +353,7 @@ async def get_motion_state(self):
339353

340354
if json_data is None:
341355
_LOGGER.error(
342-
"Unable to get Motion detection state at IP %s",
343-
self._host
356+
"Unable to get Motion detection state at IP %s", self._host
344357
)
345358
self._motion_state = False
346359
return self._motion_state
@@ -357,7 +370,7 @@ async def get_still_image(self):
357370
param = {"cmd": "Snap", "channel": self._channel}
358371

359372
response = await self.send(None, param)
360-
if response is None or response == b'':
373+
if response is None or response == b"":
361374
return
362375

363376
return response
@@ -375,12 +388,12 @@ async def get_stream_source(self):
375388
stream_source = f"rtmp://{self._host}:{self._rtmp_port}/bcs/channel{self._channel}_{self._stream}.bcs?channel={self._channel}&stream=0&token={self._token}"
376389
else:
377390
password = parse.quote(self._password)
378-
channel = "{:02d}".format(self._channel+1)
379-
stream_source = f"rtsp://{self._username}{password}@{self._host}:{self._rtsp_port}/h264Preview_{channel}_{self._stream}"
391+
channel = "{:02d}".format(self._channel + 1)
392+
stream_source = f"rtsp://{self._username}:{password}@{self._host}:{self._rtsp_port}/h264Preview_{channel}_{self._stream}"
380393

381394
return stream_source
382395

383-
async def map_json_response(self, json_data): #pylint: disable=too-many-branches
396+
async def map_json_response(self, json_data): # pylint: disable=too-many-branches
384397
"""Map the JSON objects to internal objects and store for later use."""
385398
for data in json_data:
386399
try:
@@ -462,7 +475,7 @@ async def map_json_response(self, json_data): #pylint: disable=too-many-branches
462475
elif data["cmd"] == "GetAbility":
463476
for ability in data["value"]["Ability"]["abilityChn"]:
464477
self._ptz_support = ability["ptzCtrl"]["permit"] != 0
465-
except: #pylint: disable=bare-except
478+
except: # pylint: disable=bare-except
466479
continue
467480

468481
async def login(self):
@@ -472,15 +485,20 @@ async def login(self):
472485

473486
_LOGGER.debug(
474487
"Reolink camera with host %s:%s trying to login with user %s",
475-
self._host, self._port, self._username
488+
self._host,
489+
self._port,
490+
self._username,
476491
)
477492

478493
body = [
479494
{
480495
"cmd": "Login",
481496
"action": 0,
482497
"param": {
483-
"User": {"userName": self._username, "password": self._password[:31]}
498+
"User": {
499+
"userName": self._username,
500+
"password": self._password[:31],
501+
}
484502
},
485503
}
486504
]
@@ -494,7 +512,9 @@ async def login(self):
494512
json_data = json.loads(response)
495513
_LOGGER.debug("Get response from %s: %s", self._host, json_data)
496514
except (TypeError, json.JSONDecodeError):
497-
_LOGGER.debug("Host %s: Error translating login response to json", self._host)
515+
_LOGGER.debug(
516+
"Host %s: Error translating login response to json", self._host
517+
)
498518
return False
499519

500520
if json_data is not None:
@@ -505,7 +525,9 @@ async def login(self):
505525

506526
_LOGGER.debug(
507527
"Reolink camera logged in at IP %s. Leasetime %s, token %s",
508-
self._host, self._lease_time.strftime('%d-%m-%Y %H:%M'), self._token
528+
self._host,
529+
self._lease_time.strftime("%d-%m-%Y %H:%M"),
530+
self._token,
509531
)
510532
return True
511533

@@ -519,13 +541,15 @@ async def is_admin(self):
519541
if user["level"] == "admin":
520542
_LOGGER.debug(
521543
"User %s has authorisation level %s",
522-
self._username, user['level']
544+
self._username,
545+
user["level"],
523546
)
524547
else:
525548
_LOGGER.warning(
526549
"""User %s has authorisation level %s. Only admin users can change
527550
camera settings! Switches will not work.""",
528-
self._username, user['level']
551+
self._username,
552+
user["level"],
529553
)
530554

531555
async def logout(self):
@@ -691,15 +715,13 @@ async def set_sensitivity(self, value: int, preset=None):
691715
{
692716
"cmd": "SetAlarm",
693717
"action": 1,
694-
"param": {
718+
"param": {
695719
"Alarm": {
696720
"channel": 0,
697721
"type": "md",
698-
"sens":
699-
self._alarm_settings["value"]["Alarm"]["sens"],
700-
722+
"sens": self._alarm_settings["value"]["Alarm"]["sens"],
701723
}
702-
}
724+
},
703725
}
704726
]
705727
for setting in body[0]["param"]["Alarm"]["sens"]:
@@ -709,7 +731,7 @@ async def set_sensitivity(self, value: int, preset=None):
709731
return await self.send_setting(body)
710732

711733
async def set_ptz_command(self, command, preset=None, speed=None):
712-
'''Send PTZ command to the camera.
734+
"""Send PTZ command to the camera.
713735
714736
List of possible commands
715737
--------------------------
@@ -730,7 +752,7 @@ async def set_ptz_command(self, command, preset=None, speed=None):
730752
ToPos X X
731753
Auto
732754
Stop
733-
'''
755+
"""
734756

735757
body = [
736758
{
@@ -750,8 +772,7 @@ async def send_setting(self, body):
750772
"""Send a setting."""
751773
command = body[0]["cmd"]
752774
_LOGGER.debug(
753-
"Sending command: %s to: %s with body: %s",
754-
command, self._host, body
775+
"Sending command: %s to: %s with body: %s", command, self._host, body
755776
)
756777
response = await self.send(body, {"cmd": command})
757778
if response is None:
@@ -768,10 +789,16 @@ async def send_setting(self, body):
768789

769790
return False
770791
except (TypeError, json.JSONDecodeError):
771-
_LOGGER.debug("Host %s: Error translating %s response to json", self._host, command)
792+
_LOGGER.debug(
793+
"Host %s: Error translating %s response to json", self._host, command
794+
)
772795
return False
773796
except KeyError:
774-
_LOGGER.debug("Host %s: Received an unexpected response while sending command: %s", self._host, command)
797+
_LOGGER.debug(
798+
"Host %s: Received an unexpected response while sending command: %s",
799+
self._host,
800+
command,
801+
)
775802
return False
776803

777804
async def send(self, body, param=None):
@@ -781,7 +808,7 @@ async def send(self, body, param=None):
781808
return False
782809

783810
if not param:
784-
param={}
811+
param = {}
785812
if self._token is not None:
786813
param["token"] = self._token
787814

@@ -799,9 +826,12 @@ async def send(self, body, param=None):
799826
return json_data
800827

801828
except aiohttp.ClientConnectorError as conn_err:
802-
_LOGGER.debug('Host %s: Connection error %s', self._host, str(conn_err))
829+
_LOGGER.debug("Host %s: Connection error %s", self._host, str(conn_err))
803830
except asyncio.TimeoutError:
804-
_LOGGER.debug('Host %s: connection timeout exception. Please check the connection to this camera.', self._host)
805-
except: #pylint: disable=bare-except
806-
_LOGGER.debug('Host %s: Unknown exception occurred.', self._host)
831+
_LOGGER.debug(
832+
"Host %s: connection timeout exception. Please check the connection to this camera.",
833+
self._host,
834+
)
835+
except: # pylint: disable=bare-except
836+
_LOGGER.debug("Host %s: Unknown exception occurred.", self._host)
807837
return

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
setup(
33
name = 'reolink',
44
packages = ['reolink'],
5-
version = '0.0.12',
5+
version = '0.0.13',
66
license='MIT',
77
description = 'Reolink camera package',
88
author = 'fwestenberg',
99
author_email = '',
1010
url = 'https://github.com/fwestenberg/reolink',
11-
download_url = 'https://github.com/fwestenberg/reolink/archive/v_011.tar.gz',
11+
download_url = 'https://github.com/fwestenberg/reolink/archive/v_013.tar.gz',
1212
keywords = ['Reolink', 'Home-Assistant'],
1313
install_requires=[
1414
'ffmpeg',

0 commit comments

Comments
 (0)