fwestenberg / reolink_dev

Home Assistant Reolink addon
MIT License
550 stars 102 forks source link

Apparent bug - "Failed to connect with the camera"- Reolink Duo #362

Closed ptyers closed 2 years ago

ptyers commented 2 years ago

Ver 0.36 Home Assistant 2021.11.2

When attempting to add integration for Reolink Duo camera entering the following

Host 192.168.80.43 Port 80 (although same effect with 443 and https ticked) use https cleared username camerauser password camera

comes back with virgin form and error message "Failed to connect with the camera" I have tracked the process as far as the following code in base.py

       if not await self._api.get_settings():
        return False

    if not await self._api.get_states():
        return False

appears to sucessfully execute _api.get_settings but fails in _api.get_states

If incorrect IP or username/password used fails in _api.get_settings as expected, although with non useful error message "Unexpected Error"

Installation was as per doco. HACS - enter custom repository - install - reboot - configurations - integrations - reolink

Camera can be sucessfully installed using ONVIF integration but I was hoping to use the motion sensing entity.

ptyers commented 2 years ago

log reolink.txt

result of setting log level for package reolink to debug request in camera_api..get_states returns status 502 Bad Gateway obviously camera does not like one of the requested parameters.

cpainchaud commented 2 years ago

It looks like your camera is crashing on the following API call:

[{'cmd': 'GetFtp', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetEnc', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetEmail', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetIsp', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetIrLights', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetPtzPreset', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetHddInfo', 'action': 1, 'param': {}}, {'cmd': 'GetAlarm', 'action': 1, 'param': {'Alarm': {'channel': 0, 'type': 'md'}}}, {'cmd': 'GetPushV20', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetRecV20', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetPush', 'action': 1, 'param': {'channel': 0}}, {'cmd': 'GetRec', 'action': 1, 'param': {'channel': 0}}]

Provided that Reolink is not publishing their API specs, you will have to fish for the query which is crashing your system. Please try each individual 'Cmd' to find which one(s) are crashing your camera:

curl -k  "https://yourcamera/cgi-bin/api.cgi?cmd=GetRec&user=admin&password=password"
curl -k  "https://yourcamera/cgi-bin/api.cgi?cmd=GetFtp&user=admin&password=password"
curl -k  "https://yourcamera/cgi-bin/api.cgi?cmd=GetPush&user=admin&password=password"
... etc ...
ptyers commented 2 years ago

ThanksI am currently in process of doing that but was attempting to do it under program call. My other theory is that the camera could be choking on the multiple commands hitting it in a short time. To be confirmed one way or the other.

ptyers commented 2 years ago

further info

as advised ran a script containing curl commands for each of cmd calls in get_states, output including echoed curl statement attached. Cannot say for certain but it would appear that all calls succeeded. Could the problem be that camera chokes on volume of calls coming in close succession from get_states rather than due to any specific call failing?

curl and output.txt

widewings007 commented 2 years ago

I have the same problem with Reolink Duo PoE.

My Reolink 810A works fine.

ptyers commented 2 years ago

I was not sufficiently competant to create a local version of the reolink package but using the _api object created in base.py and emulating the guts of get_states within base.py I have determined that the offending command is getPush in get_states. log extract

2021-11-17 13:08:10 DEBUG (MainThread) [reolink.camera_api] send() HTTP Request params ={'token': '43284a63edaf48c'} 2021-11-17 13:08:10 DEBUG (MainThread) [reolink.camera_api] send() HTTP Request body =[{'cmd': 'GetPush', 'action': 1, 'param': {'channel': 1}}] 2021-11-17 13:08:10 DEBUG (MainThread) [reolink.camera_api] send() HTTP Response status=502 content-type=(text/html) 2021-11-17 13:08:10 DEBUG (MainThread) [reolink.camera_api.data] send() HTTP Response data:

502 Bad Gateway

502 Bad Gateway


nginx

I have cloned the reolink git reposity and am currently working on a branch to preclude this command being appended to the body object in get_states. I know that get_settings.GetDevInfo returns Model = "Reolink Duo PoE" for my unit but need to know what the returns are for the WiFi, and 4G models. I will be assuming "Reolink Duo WiFi"and "Reolink Duo 4G" in the code I will be proposing. A smarter coder than I will probably be able to reduce the test to "Reolink Duo" using a regex.

ptyers commented 2 years ago

Unable to load branch due to problems with PAT.

Suggest replace code in camera_api.get_states with

if not self._is_nvr and (self._sw_version_object < ref_sw_version_3_1_0_0_0 or not self.is_ia_enabled):

NVR would crash without this

        if not ( self.model.startswith("Reolink Duo")):
            body.append({"cmd": "GetPush", "action": 1, "param": {"channel": self._channel}})

        body.append({"cmd": "GetRec", "action": 1, "param": {"channel": self._channel}})
cpainchaud commented 2 years ago

this is strange since that API call curl -k https://192.168.80.43/cgi-bin/api.cgi?cmd=GetPush&user=camerauser&password=camera did not cause a crash for you

ptyers commented 2 years ago

I agree. But no matter what I do if I use {"cmd": "GetPush", "action": 1, "param": {"channel": self._channel}} or {"cmd": "GetPush", "action": 1}
(which appears to be the format referenced in "Camera HTTP API User Guide" referenced by Ovid in the issue raised re Spotlights on the Reolink repository and which states that only the action parameter is required)

the load fails with a Bad Gateway message GetPush doco.pdf .

cpainchaud commented 2 years ago

actually it should be using GetPushV20 instead of GetPush . Reolink's poor quality code is not cleaning up old/unused features. I need to see what's the best way to address this in the underlying library

ptyers commented 2 years ago

Yes I missed that one. Maybe the reolink package needs a conditional (similar to the NVR check) dependent on the firmware status returned from get_settings to determine if the GetPush/GetRec commands are entered into the command block?

ptyers commented 2 years ago

Latest update to reolink library re GetPush/GetRec versions seems to have fixed the problem. Thanks to cpainchaud!!