fwestenberg / reolink_dev

Home Assistant Reolink addon
MIT License
551 stars 101 forks source link

A bytes-like object is required, not 'NoneType' #189

Open sylarevan opened 3 years ago

sylarevan commented 3 years ago

Describe the bug I'm trying to use the snapshot service to get an image from my RLC-423. I get a 0 byte file instead. Using deepstack to detect objects in the image also results in "Unable to get image".

To Reproduce Call to service:

service: camera.snapshot
data:
  filename: /media/test.jpg
target:
  entity_id: camera.jardin

Environment:

Additional context Error log:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 359, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 559, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1515, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 206, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 649, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 692, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 686, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 651, in async_handle_snapshot_service
    await hass.async_add_executor_job(_write_image, snapshot_file, image)
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 648, in _write_image
    img_file.write(image_data)
TypeError: a bytes-like object is required, not 'NoneType'
2021-05-14 20:51:08 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection] [140266228947072] Error handling message: Unknown error
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 18, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 439, in handle_execute_script
    await script_obj.async_run(context=context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1200, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 341, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 359, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 559, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1515, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 206, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 649, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 692, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 686, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 651, in async_handle_snapshot_service
    await hass.async_add_executor_job(_write_image, snapshot_file, image)
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 648, in _write_image
    img_file.write(image_data)
TypeError: a bytes-like object is required, not 'NoneType'

The addon is configured to use rtsp stream. Using AlexxIT/WebRTC custom component for viewing the rtsp stream, or the camera stream from HA, both work OK, even when the error above occurs.

sylarevan commented 3 years ago

FWIW, I'm still not able to get any snapshot with 2021.5.4

sylarevan commented 3 years ago

Tested with version 0.17, I am still not able to get a snapshot from the camera, with still the same error message: websocket_api script: Error executing script. Unexpected error for call_service at pos 1: a bytes-like object is required, not 'NoneType'

fwestenberg commented 3 years ago

Strange! This works in my case:

IMG_20210531_225453

sylarevan commented 3 years ago

On my side :

Capture d’écran 2021-06-01 à 22 12 04

And in the log:


Logger: homeassistant.components.websocket_api.http.connection
Source: components/camera/__init__.py:636
Integration: Home Assistant WebSocket API (documentation, issues)
First occurred: 31 mai 2021 à 22:41:38 (3 occurrences)
Last logged: 22:12:03

    [139686214610896] Error handling message: Unknown error
    [139683877403712] Error handling message: Unknown error

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/decorators.py", line 21, in _handle_async_response
    await func(hass, connection, msg)
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 482, in handle_execute_script
    await script_obj.async_run(msg.get("variables"), context=context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1212, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 348, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 366, in _async_step
    await getattr(self, handler)()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 566, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1481, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1516, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 213, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 658, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 726, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 695, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 639, in async_handle_snapshot_service
    await hass.async_add_executor_job(_write_image, snapshot_file, image)
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/homeassistant/homeassistant/components/camera/__init__.py", line 636, in _write_image
    img_file.write(image_data)
TypeError: a bytes-like object is required, not 'NoneType'
fwestenberg commented 3 years ago

Seems like your camera is not providing an image for some reason. Your one of the first I hear about the RLC-423. I assume the firmware is up to date (pls check at the Reolink site manually) and the API is working the same way as the other cams..?

sylarevan commented 3 years ago

I can confirm the camera firmware is up to date, and as far as I know the API is the same as other cameras. For instance, I can control my camera PTZ through the reolink_dev.ptz_control service just fine. But you gave me an idea: I will try to use the API directly and check if I'm able to get a snapshot from it.

fwestenberg commented 3 years ago

Thanks, please let me know!

sylarevan commented 3 years ago

Well, here is what i get. The following address does not return anything ... which sounds very similar to the error I get: curl "http://XX.XX.XX.XX/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=10a&user=myuser&password=mypassword"

But as soon as I add a width and height parameter in the URL, I am able to get a snapshot: curl "http://XX.XX.XX.XX/cgi-bin/api.cgi?cmd=Snap&channel=0&rs=10a&width=320&height=240&user=myuser&password=mypassword"

Are some width and height parameters sent by the integration to the camera?

fwestenberg commented 3 years ago

The integration does not send these parameters, I even didn't know they exist. Is this documented somewhere? I need to find out what options can be used and on what camera models.

sylarevan commented 3 years ago

I used the following page, which is written in french but still quite self explanatory. It points towards different documents and API documentations, in which these width and height are not specifically mentioned.

But I'm now quite confident this is the reason of my "bug". Would there be any way to add these width and height parameters as a parameter of the HA snapshot service?

fwestenberg commented 3 years ago

Interesting! Not all of my camera's support this, but maybe a firmware update will help. But my working cam responds a bit odd (on top the requested size, below the real size):

IMG_20210602_183419

sylarevan commented 3 years ago

On my RLC-423, not all values can be used. With some more or less random width/height values, I get: [ { "cmd" : "Snap", "code" : 1, "error" : { "detail" : "rcv failed", "rspCode" : -17 } } ]

But for standard values (e.g. 1024 x 768) this works well. And again, without any value, I just receive an empty response (but still , no error message).

fwestenberg commented 3 years ago

After updating my RLC-410 and RLC-420 both support these parameters. Also the picture size corresponds to the requested size. Strange but also without parameters I still get the (full size) image.

fwestenberg commented 3 years ago

I will add the parameters soon. Please be patient!

sylarevan commented 3 years ago

👍🏻 Thanks a lot!

fwestenberg commented 3 years ago

One problem here is, the service is the default camera service (snapshot). So I don't think enhancing the service with extra data is an option. I can add extra parameters to the configuration screen for the snapshot size (but you can't change this using a service in your automation for example). Would that be sufficient?

fwestenberg commented 3 years ago

Another option is to create a custom snapshot service: reolink_dev.snapshot.

sylarevan commented 3 years ago

Both solutions seem fine to me, at least for my specific use case:

Pick the simplest for you ;) But maybe the custom service is a bit more "generic"?