Files
reolink_api/APIHandler.py
Alano Terblanche e7cdd19dfe Small changes and Snap Frame addition.
Snap allows for the retrieval of a single frame from the current Camera video stream.
PEP8 standard implemented.
2019-08-10 21:47:57 +02:00

226 lines
7.3 KiB
Python

import io
import json
import random
import string
from urllib.request import urlopen
from PIL import Image
from resthandle import Request
class APIHandler:
"""
The APIHandler class is the backend part of the API.
This handles communication directly with the camera.
All Code will try to follow the PEP 8 standard as described here: https://www.python.org/dev/peps/pep-0008/
"""
def __init__(self, ip: str, username: str, password: str):
"""
Initialise the Camera API Handler (maps api calls into python)
:param ip:
:param username:
:param password:
"""
self.url = "http://" + ip + "/cgi-bin/api.cgi"
self.token = None
self.username = username
self.password = password
# Token
def login(self):
"""
Get login token
Must be called first, before any other operation can be performed
:return:
"""
try:
body = [{"cmd": "Login", "action": 0,
"param": {"User": {"userName": self.username, "password": self.password}}}]
param = {"cmd": "Login", "token": "null"}
response = Request.post(self.url, data=body, params=param)
if response is not None:
data = json.loads(response.text)[0]
code = data["code"]
if int(code) == 0:
self.token = data["value"]["Token"]["name"]
print("Login success")
print(self.token)
else:
print("Failed to login\nStatus Code:", response.status_code)
except Exception as e:
print("Error Login\n", e)
raise
###########
# NETWORK
###########
###########
# SET Network
###########
def set_net_port(self, httpPort=80, httpsPort=443, mediaPort=9000, onvifPort=8000, rtmpPort=1935, rtspPort=554):
"""
Set network ports
If nothing is specified, the default values will be used
:param httpPort:
:param httpsPort:
:param mediaPort:
:param onvifPort:
:param rtmpPort:
:param rtspPort:
:return:
"""
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "SetNetPort", "action": 0, "param": {"NetPort": {
"httpPort": httpPort,
"httpsPort": httpsPort,
"mediaPort": mediaPort,
"onvifPort": onvifPort,
"rtmpPort": rtmpPort,
"rtspPort": rtspPort
}}}]
param = {"token": self.token}
response = Request.post(self.url, data=body, params=param)
if response is not None:
if response.status_code == 200:
print("Successfully Set Network Ports")
else:
print("Something went wront\nStatus Code:", response.status_code)
except Exception as e:
print("Setting Network Port Error\n", e)
raise
def set_wifi(self, ssid, password):
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "SetWifi", "action": 0, "param": {
"Wifi": {
"ssid": ssid,
"password": password
}}}]
param = {"cmd": "SetWifi", "token": self.token}
response = Request.post(self.url, data=body, params=param)
return json.loads(response.text)
except Exception as e:
print("Could not Set Wifi details", e)
raise
###########
# GET
###########
def get_net_ports(self):
"""
Get network ports
:return:
"""
try:
if self.token is not None:
raise ValueError("Login first")
body = [{"cmd": "GetNetPort", "action": 1, "param": {}},
{"cmd": "GetUpnp", "action": 0, "param": {}},
{"cmd": "GetP2p", "action": 0, "param": {}}]
param = {"token": self.token}
response = Request.post(self.url, data=body, params=param)
return json.loads(response.text)
except Exception as e:
print("Get Network Ports", e)
def get_link_local(self):
"""
Get General network data
This includes IP address, Device mac, Gateway and DNS
:return:
"""
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "GetLocalLink", "action": 1, "param": {}}]
param = {"cmd": "GetLocalLink", "token": self.token}
request = Request.post(self.url, data=body, params=param)
return json.loads(request.text)
except Exception as e:
print("Could not get Link Local", e)
raise
def get_wifi(self):
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "GetWifi", "action": 1, "param": {}}]
param = {"cmd": "GetWifi", "token": self.token}
response = Request.post(self.url, data=body, params=param)
return json.loads(response.text)
except Exception as e:
print("Could not get Wifi\n", e)
raise
def scan_wifi(self):
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "ScanWifi", "action": 1, "param": {}}]
param = {"cmd": "ScanWifi", "token": self.token}
response = Request.post(self.url, data=body, params=param)
return json.loads(response.text)
except Exception as e:
print("Could not Scan wifi\n", e)
raise
###########
# SYSTEM
###########
###########
# GET
###########
def get_general_system(self):
try:
if self.token is None:
raise ValueError("Login first")
body = [{"cmd": "GetTime", "action": 1, "param": {}}, {"cmd": "GetNorm", "action": 1, "param": {}}]
param = {"token": self.token}
response = Request.post(self.url, data=body, params=param)
return json.loads(response.text)
except Exception as e:
print("Could not get General System settings\n", e)
raise
##########
# Image Data
##########
def get_snap(self, timeout=3) -> Image or None:
"""
Gets a "snap" of the current camera video data and returns a Pillow Image or None
:param timeout:
:return:
"""
try:
randomstr = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))
snap = "?cmd=Snap&channel=0&rs=" \
+ randomstr \
+ "&user=" + self.username \
+ "&password=" + self.password
reader = urlopen(self.url + snap, timeout)
if reader.status == 200:
b = bytearray(reader.read())
return Image.open(io.BytesIO(b))
print("Could not retrieve data from camera successfully. Status:", reader.status)
return None
except Exception as e:
print("Could not get Image data\n", e)
raise