tchellomello / python-amcrest

A Python 2.7/3.x module for Amcrest and Dahua Cameras using the SDK HTTP API.
GNU General Public License v2.0
216 stars 76 forks source link

snapshot() does not work for some cameras (HASS: Amcrest Cameras fail after update to 0.59.1) #86

Closed akerrichardt closed 5 years ago

akerrichardt commented 6 years ago

Description of problem:After upgrade to 0.59.1 only 1 of my Amcrest cameras output appear in both of my Amcrest cameras displays on the Dashboard.

I upgrade my RPI 3 running on Raspbian Stretch Desktop to HA version 0.60.0. Still having the same trouble with my Amcrest Cameras. I did see this in the Info tab if this helps!! Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'ProtocolError('Connection aborted.', RemoteDisconnected('Remote end closed connection without response',))': /cgi-bin/snapshot.cgi?channel=0 2:18 PM components/camera/amcrest.py (WARNING)

dougsland commented 6 years ago

@akerrichardt have you upgraded the firmware of your cameras recently? Do you know which firmware these cameras are running?

Finally, could you please share your amcrest settings from configuration.yaml (removing the username/password) ?

tchellomello commented 6 years ago

@akerrichardt I just updated mine HASS and I got the same issue on 0.60.1. I'll take a look at what is going on in 2 weeks since I'm leaving on vacations.

tchellomello commented 6 years ago

Quick update... I have 4 amcrest cameras running with HASS. 2 of them are working and 2 are failing.

Working Build Date: build:2017-06-29 Version: 2.520.AC00.18.R

Failing Build Date: build:2017-03-28 Version: 2.400.AC01.15.R

An important note is that I'm getting the error on the HASS webui, however if I click on the image I can see the live stream:

image But if I click: image

So this seems to be a problem with a newer fewer as we can note on the test below: working one return a valid JPG image

(python:ha-py36) ↪ amcrest-cli --camera amcrestcam1  --snapshot 1 --save ~/Desktop/lala.jpg ; file ~/Desktop/lala.jpg 
/home/mdemello/Desktop/lala.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, comment: "", comment: "DHAV\373", baseline, precision 8, 1920x1080, frames 3

failing one

(python:ha-py36) ↪ amcrest-cli --camera amcrestcam4  --snapshot 1 --save ~/Desktop/lala.jpg ; file ~/Desktop/lala.jpg 
/home/mdemello/Desktop/lala.jpg: empty

Troubleshooting via RPB:

In [3]: camera.software_information
Out[3]: ('version=2.400.AC01.15.R', 'build:2017-03-28\r\n')

In [4]: camera.snapshot(0, "/home/user/Desktop/snapshot00.jpeg")
pdb is running on 127.0.0.1:4444

(Pdb) ret
<Response [401]>

(Pdb) ret.headers
{'WWW-Authenticate': 'Digest realm="Login to AMC02<REDACTED>",qop="auth",nonce="392412475",opaque="bb5e1d12c0f69db4ae07a9cb8c901c07c"', 'Connection': 'close', 'CONTENT-LENGTH': '0'}

(Pdb) ret.status_code
401

Firmware changelog: https://s3.amazonaws.com/amcrest-files/Firmware/IP3M-956_IP3M-943_IPM-723_IPM-751_Changelog_7-31-17.txt

@dougsland is your cameras working fine?

tchellomello commented 6 years ago

Digging a little bit more into this, I'm getting 500 errors when trying to snapshot.

In [24]: req = requests.get(url, auth=auth2, stream=True)

In [25]: req
Out[25]: <Response [500]>

In [26]: url
Out[26]: 'http://192.168.0.1:80/cgi-bin/snapshot.cgi?channel=0'

In [27]: auth2
Out[27]: <requests.auth.HTTPDigestAuth at 0x7fcd0c1680f0>

I think the next step to troubleshoot what is going on is to put a sniffer between the application and the camera to see what is going on.

tchellomello commented 6 years ago

One temporarly alternative would be to gather the screenshot via ffmpeg within HASS, however it will not address the issue on python-amcrest. The problem is since it works for a few camera models and it fails for others, it seems the issue relies on the firmware side, which then makes a little bit harder to troubleshoot it.

tchellomello commented 6 years ago

Other people hitting the same issue: https://amcrest.com/forum/viewtopic.php?f=3&t=3060&p=10410&hilit=snapshot+API#p10410

tchellomello commented 6 years ago

Modified the HASS amcrest code to use ffmpeg to generate the snapshot and it worked as expected.

--- a/homeassistant/components/camera/amcrest.py
+++ b/homeassistant/components/camera/amcrest.py
@@ -50,11 +50,19 @@ class AmcrestCam(Camera):
         self._resolution = amcrest.resolution
         self._token = self._auth = amcrest.authentication

-    def camera_image(self):
+    @asyncio.coroutine
+    def async_camera_image(self):
         """Return a still image response from the camera."""
-        # Send the request to snap a picture and return raw jpg data
-        response = self._camera.snapshot(channel=self._resolution)
-        return response.data
+        from haffmpeg import ImageFrame, IMAGE_JPEG
+        ffmpeg = ImageFrame(self._ffmpeg.binary, loop=self.hass.loop)
+        streaming_url = self._camera.rtsp_url(typeno=self._resolution)
+        if streaming_url is None:
+            return
+
+        image = yield from asyncio.shield(ffmpeg.get_image(
+            streaming_url, output_format=IMAGE_JPEG,
+            extra_cmd=self._ffmpeg_arguments), loop=self.hass.loop)
+        return image

     @asyncio.coroutine
     def handle_async_mjpeg_stream(self, request):

image

@akerrichardt I'm going to create a test file so then you drop on your custom_components to test it

tchellomello commented 6 years ago

How to install hotfix on HASS:

  1. Create a custom_components directory on the same level you have the configuration.yaml file. On this example, I have it under /home/hass/.homeassistant
    cd /home/hass/.homeassistant
    mkdir -p custom_components/camera
  2. Download the https://raw.githubusercontent.com/tchellomello/home-assistant/hotfix_amcrest/homeassistant/components/camera/amcrest.py file on that custom_components/camera directory
wget https://raw.githubusercontent.com/tchellomello/home-assistant/hotfix_amcrest/homeassistant/components/camera/amcrest.py -O /home/hass/custom_components/camera/amcrest.py
  1. Make sure you have ffmpeg installed and configured on your HA. https://home-assistant.io/components/ffmpeg/

This should workaround the issue for now. @akerrichardt Please let me know if that worked for you

hawkeyeP commented 6 years ago

I'm not sure if this will help you with a fix, but I tried my own manual fix to use in appdaemon and found that the HTTPDigestAuth needed to be used:

   r  = requests.get('http://yourIP/cgi-bin/snapshot.cgi?channel=0', auth=HTTPDigestAuth('username', 'password'), stream=True)

    with open(pic_name, 'wb') as out_file:
        r.raw.decode_content = True
        shutil.copyfileobj(r.raw, out_file)

    del r
pnbruckner commented 5 years ago

Hi all. I suspect these problems have been addressed by recent updates to this package as well as the HA amcrest component. I'm going to close this, but feel free to reopen if necessary.