Skip to content
This repository has been archived by the owner on Apr 6, 2023. It is now read-only.

Commit

Permalink
Merge pull request #22 from fwestenberg/Add-NVR-support
Browse files Browse the repository at this point in the history
Add nvr support
  • Loading branch information
fwestenberg authored Jan 2, 2020
2 parents cb1c99a + c136557 commit 4661784
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 17 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ camera:
name: camera (optional, default Reolink Camera)
stream: main or sub (optional, default main)
protocol: rtmp or rtsp (optional, default rtmp)
channel: NVR camera channel (optional, default 0)
scan_interval: 5 (optional, default 30s)
```

Expand Down
25 changes: 15 additions & 10 deletions custom_components/reolink_dev/ReolinkPyPi/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
_LOGGER = logging.getLogger(__name__)

class ReolinkApi(object):
def __init__(self, ip):
def __init__(self, ip, channel):
self._url = "http://" + ip + "/cgi-bin/api.cgi"
self._ip = ip
self._channel = channel
self._token = None
self._motion_state = False
self._last_motion = 0
Expand All @@ -28,12 +29,13 @@ def status(self):
if self._token is None:
return

body = [{"cmd":"GetDevInfo","action":1,"param":{}},
{"cmd": "GetNetPort", "action": 1, "param": {}},
{"cmd": "GetFtp", "action": 1, "param": {}},
{"cmd":"GetEmail","action":1,"param":{}},
{"cmd":"GetIrLights","action":1,"param":{}},
{"cmd":"GetPtzPreset","action":1,"param":{"channel":0}}]
param_channel = {"channel": self._channel}
body = [{"cmd": "GetDevInfo", "action":1, "param": param_channel},
{"cmd": "GetNetPort", "action": 1, "param": param_channel},
{"cmd": "GetFtp", "action": 1, "param": param_channel},
{"cmd": "GetEmail", "action": 1, "param": param_channel},
{"cmd": "GetIrLights", "action": 1, "param": param_channel},
{"cmd": "GetPtzPreset", "action": 1, "param": param_channel}]

param = {"token": self._token}
response = self.send(body, param)
Expand Down Expand Up @@ -90,7 +92,10 @@ def status(self):

@property
def motion_state(self):
response = self.send(None, "?cmd=GetMdState&token=" + self._token)
body = [{"cmd": "GetMdState", "action": 0, "param":{"channel":self._channel}}]
param = {"token": self._token}

response = self.send(body, param)

try:
json_data = json.loads(response.text)
Expand All @@ -112,13 +117,13 @@ def motion_state(self):

@property
def still_image(self):
response = self.send(None, "?cmd=Snap&channel=0&token=" + self._token, stream=True)
response = self.send(None, f"?cmd=Snap&channel={self._channel}&token={self._token}", stream=True)
response.raw.decode_content = True
return response.raw

@property
def snapshot(self):
response = self.send(None, "?cmd=Snap&channel=0&token=" + self._token, stream=False)
response = self.send(None, f"?cmd=Snap&channel={self._channel}&token={self._token}", stream=False)
return response.content

@property
Expand Down
20 changes: 13 additions & 7 deletions custom_components/reolink_dev/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@
DEFAULT_NAME = "Reolink Camera"
DEFAULT_STREAM = "main"
DEFAULT_PROTOCOL = "rtmp"
DEFAULT_CHANNEL = 0
CONF_STREAM = "stream"
CONF_PROTOCOL = "protocol"
CONF_CHANNEL = "channel"
DOMAIN = "camera"
SERVICE_ENABLE_FTP = 'enable_ftp'
SERVICE_DISABLE_FTP = 'disable_ftp'
Expand All @@ -44,6 +46,7 @@
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_STREAM, default=DEFAULT_STREAM): vol.In(["main", "sub"]),
vol.Optional(CONF_PROTOCOL, default=DEFAULT_PROTOCOL): vol.In(["rtmp", "rtsp"]),
vol.Optional(CONF_CHANNEL, default=DEFAULT_CHANNEL): cv.positive_int,
}
)

Expand All @@ -56,12 +59,13 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
password = config.get(CONF_PASSWORD)
stream = config.get(CONF_STREAM)
protocol = config.get(CONF_PROTOCOL)
channel = config.get(CONF_CHANNEL)
name = config.get(CONF_NAME)

session = ReolinkApi(host)
session = ReolinkApi(host, channel)
session.login(username, password)

async_add_devices([ReolinkCamera(hass, session, host, username, password, stream, protocol, name)], update_before_add=True)
async_add_devices([ReolinkCamera(hass, session, host, username, password, stream, protocol, channel, name)], update_before_add=True)

# Event enable FTP
def handler_enable_ftp(call):
Expand Down Expand Up @@ -124,7 +128,7 @@ def handler_disable_ir_lights(call):
class ReolinkCamera(Camera):
"""An implementation of a Reolink IP camera."""

def __init__(self, hass, session, host, username, password, stream, protocol, name):
def __init__(self, hass, session, host, username, password, stream, protocol, channel, name):
"""Initialize a Reolink camera."""

super().__init__()
Expand All @@ -133,6 +137,7 @@ def __init__(self, hass, session, host, username, password, stream, protocol, na
self._password = password
self._stream = stream
self._protocol = protocol
self._channel = channel
self._name = name
self._reolinkSession = session
self._hass = hass
Expand Down Expand Up @@ -205,9 +210,10 @@ def ptzpresets(self):
async def stream_source(self):
"""Return the source of the stream."""
if self._protocol == "rtsp":
stream_source = f"rtsp://{self._username}:{self._password}@{self._host}:{self._reolinkSession.rtspport}/h264Preview_01_{self._stream}"
rtspChannel = f"{self._channel+1:02d}"
stream_source = f"rtsp://{self._username}:{self._password}@{self._host}:{self._reolinkSession.rtspport}/h264Preview_{rtspChannel}_{self._stream}"
else:
stream_source = f"rtmp://{self._host}:{self._reolinkSession.rtmpport}/bcs/channel0_{self._stream}.bcs?channel=0&stream=0&user={self._username}&password={self._password}"
stream_source = f"rtmp://{self._host}:{self._reolinkSession.rtmpport}/bcs/channel{self._channel}_{self._stream}.bcs?channel={self._channel}&stream=0&user={self._username}&password={self._password}"

return stream_source

Expand Down Expand Up @@ -238,13 +244,13 @@ async def async_camera_image(self):
return self._reolinkSession.snapshot

def enable_ftp_upload(self):
"""Enable motion recording in camera."""
"""Enable motion ftp recording in camera."""
if self._reolinkSession.set_ftp(True):
self._ftp_state = True
self._hass.states.set(self.entity_id, self.state, self.state_attributes)

def disable_ftp_upload(self):
"""Disable motion recording."""
"""Disable motion ftp recording."""
if self._reolinkSession.set_ftp(False):
self._ftp_state = False
self._hass.states.set(self.entity_id, self.state, self.state_attributes)
Expand Down

0 comments on commit 4661784

Please sign in to comment.