Compare commits

..

11 Commits

Author SHA1 Message Date
37b929fcbe YACWC 2025-06-20 16:33:12 -04:00
Alano Terblanche
f15171147b Merge pull request #64 from Helias/patch-1
chore: add RLC-510A in supported cameras list
2022-09-07 00:05:38 +02:00
Stefano Borzì
7999ce8108 chore: add RLC-510A in supported cameras list 2022-08-21 19:22:15 +02:00
Alano Terblanche
59945861b0 Merge pull request #63 from ReolinkCameraAPI/bump-version
chore: bump version to 0.1.5
2022-08-20 12:44:34 +02:00
Alano Terblanche
a61e86cfa4 chore: bump version to 0.1.5 2022-08-20 12:43:57 +02:00
Alano Terblanche
77eaff9edf Merge pull request #59 from deadc0de6/fix-no-value
fix KeyError: value
2022-08-20 12:40:45 +02:00
Alano Terblanche
23209f47f4 Merge pull request #62 from ReolinkCameraAPI/bump-version
chore: bump version to 0.1.4
2022-08-20 12:34:27 +02:00
Alano Terblanche
37dd49f936 chore: bump version to 0.1.4 2022-08-20 12:33:39 +02:00
deadc0de6
d59cefff52 fix KeyError: value 2022-07-31 14:46:06 +02:00
Alano Terblanche
8b6049bb26 Merge pull request #53 from AmmarKothari/use_proxy_for_downlading_files
Add proxy arg to get for downloading files
2021-12-12 23:10:17 +01:00
ammar
936c43b6fa Add proxy arg to get for downloading files 2021-12-03 16:42:52 -08:00
8 changed files with 114 additions and 8 deletions

View File

@@ -149,6 +149,7 @@ do not work and is not supported here.
- RLC-423
- RLC-420-5MP
- RLC-410-5MP
- RLC-510A
- RLC-520
- C1-Pro
- D400

View File

@@ -1,4 +1,4 @@
from reolinkapi.handlers.api_handler import APIHandler
from .camera import Camera
__version__ = "0.1.3"
__version__ = "0.1.5"

View File

@@ -2,12 +2,27 @@ from reolinkapi.handlers.api_handler import APIHandler
class Camera(APIHandler):
def __exit__(self):
if self._token is not None:
print('Logging out')
self.logout()
else:
print('not logged in, logging out')
def __del__(self):
if self._token is not None:
print('Logging out')
self.logout()
else:
print('not logged in, logging out')
def __init__(self, ip: str,
username: str = "admin",
password: str = "",
https: bool = False,
defer_login: bool = False,
defer_login: bool = True,
profile: str = "main",
**kwargs):
"""

View File

@@ -52,11 +52,28 @@ class APIHandler(AlarmAPIMixin,
scheme = 'https' if https else 'http'
self.url = f"{scheme}://{ip}/cgi-bin/api.cgi"
self.ip = ip
self.token = None
self._token = None
self.username = username
self.password = password
Request.proxies = kwargs.get("proxy") # Defaults to None if key isn't found
def __getattr__(self, name):
if name == 'token':
if self._token is None:
self.login()
return self._token
else:
return getattr(self, name)
def __del__(self):
if self._token is not None:
print('Logging out')
self.logout()
else:
print('not logged in, logging out')
def login(self) -> bool:
"""
Get login token
@@ -72,7 +89,7 @@ class APIHandler(AlarmAPIMixin,
data = response.json()[0]
code = data["code"]
if int(code) == 0:
self.token = data["value"]["Token"]["name"]
self._token = data["value"]["Token"]["name"]
print("Login success")
return True
print(self.token)
@@ -95,6 +112,7 @@ class APIHandler(AlarmAPIMixin,
try:
data = [{"cmd": "Logout", "action": 0}]
self._execute_command('Logout', data)
self._token = None
# print(ret)
return True
except Exception as e:
@@ -124,7 +142,7 @@ class APIHandler(AlarmAPIMixin,
tgt_filepath = data[0].pop('filepath')
# Apply the data to the params
params.update(data[0])
with requests.get(self.url, params=params, stream=True, verify=False, timeout=(1, None)) as req:
with requests.get(self.url, params=params, stream=True, verify=False, timeout=(1, None), proxies=Request.proxies) as req:
if req.status_code == 200:
with open(tgt_filepath, 'wb') as f:
f.write(req.content)

View File

@@ -12,3 +12,7 @@ class AlarmAPIMixin:
"""
body = [{"cmd": "GetAlarm", "action": 1, "param": {"Alarm": {"channel": 0, "type": "md"}}}]
return self._execute_command('GetAlarm', body)
def get_ai_state(self) -> Dict:
body = [{"cmd": "GetAIState"}]
return self._execute_command('GetAlarm', body)

View File

@@ -46,7 +46,12 @@ class MotionAPIMixin:
body = [{"cmd": "Search", "action": 1, "param": search_params}]
resp = self._execute_command('Search', body)[0]
result = resp['value']['SearchResult']
if 'value' not in resp:
return []
values = resp['value']
if 'SearchResult' not in values:
return []
result = values['SearchResult']
files = result.get('File', [])
if len(files) > 0:
# Begin processing files

View File

@@ -1,5 +1,5 @@
from typing import Dict
import time
class PtzAPIMixin:
"""
@@ -121,3 +121,65 @@ class PtzAPIMixin:
:return: response json
"""
return self._send_operation('Auto', speed=speed)
def get_zoom_focus_pos(self) -> Dict:
body = [{"cmd": "GetZoomFocus", "action": 0, "param": {'channel':0}}]
return self._execute_command('GetZoomFocus',body)
def set_auto_focus_state(self, state: bool = True) -> Dict:
body = [{"cmd": "SetAutoFocus", "action": 0, "param": {'AutoFocus':{'channel':0,'disable':int(state)}}}]
return self._execute_command('SetAutoFocus',body)
def get_auto_focus_state(self) -> bool:
body = [{"cmd": "GetAutoFocus", "action": 1, "param": {'channel':0}}]
return bool(self._execute_command('GetAutoFocus',body)[0]['value']['AutoFocus']['disable'])
def set_zoom_pos(self, pos: int) -> Dict:
body = [{"cmd": "StartZoomFocus", "action": 0, "param": {'ZoomFocus':{'channel':0,'pos':pos,'op':'ZoomPos'}}}]
self._execute_command('StartZoomFocus',body)
def set_focus_pos(self, pos: int) -> Dict:
body = [{"cmd": "StartZoomFocus", "action": 0, "param": {'ZoomFocus':{'channel':0,'pos':pos,'op':'FocusPos'}}}]
self._execute_command('StartZoomFocus',body)
def generic_set_block(self, pos:int, get_func, set_func) -> int:
change_index = 0
last_pos = get_func()
pos = min([pos,254])
pos = max([pos, 0])
target_pos = pos
set_func(pos)
for i in range(100):
cpos = get_func()
if cpos != last_pos:
change_index = i
if cpos == target_pos:
break
if (i - change_index) > 8:
break
last_pos = cpos
time.sleep(0.25)
return cpos
def set_focus_pos_block(self, pos: int) -> int:
return self.generic_set_block(pos, self.get_focus_pos, self.set_focus_pos)
def set_zoom_pos_block(self, pos: int) -> int:
return self.generic_set_block(pos, self.get_zoom_pos, self.set_zoom_pos)
def get_zoom_pos(self) -> int:
return self.get_zoom_focus_pos()[0]['value']['ZoomFocus']['zoom']['pos']
def get_focus_pos(self) -> int:
return self.get_zoom_focus_pos()[0]['value']['ZoomFocus']['focus']['pos']

View File

@@ -1 +1,2 @@
.
Pillow
opencv-python