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

get_day_night_color > list index out of range error #225

Open GaryOkie opened 1 year ago

GaryOkie commented 1 year ago

On occasion a camera doesn't respond with all the expected values. Ideally the code should check for unexpected values and handle them gracefully.

On several occasions I've seen a perfectly operating camera not being able to initialize in Home Assistant with this index out of range error. I've seen reports from others that have experienced this as well - such as: https://github.com/home-assistant/core/issues/30216

I've tracked this problem down to the async_get_day_night_color call expecting VideoInOptions[0].DayNightColor=n to be returned in the response. When it is inexplicably missing, the following error results:

2023-02-12 16:18:35.484 ERROR (MainThread) [homeassistant.components.camera] amcrest: Error on device update!
Traceback (most recent call last):
File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 507, in _async_add_entity
await entity.async_device_update(warning=False)
File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 739, in async_device_update
await task
File "/usr/src/homeassistant/homeassistant/components/amcrest/camera.py", line 411, in async_update
) = await asyncio.gather(
File "/usr/src/homeassistant/homeassistant/components/amcrest/camera.py", line 641, in _async_get_color_mode
return _CBW[await self._api.async_day_night_color]
File "/usr/local/lib/python3.10/site-packages/amcrest/video.py", line 261, in async_day_night_color
return await self.async_get_day_night_color(channel=0)
File "/usr/local/lib/python3.10/site-packages/amcrest/video.py", line 285, in async_get_day_night_color
return values[channel]
IndexError: list index out of range

This is the video.py code section that throws this error when the result is undefined:

    async def async_get_day_night_color(self, channel: int) -> int:
        """
        Return Day & Night Color Mode for Day profile.

        Result is 0: always multicolor
                  1: autoswitch along with brightness
                  2: always monochrome                                   
        """                          
        values = [
            int(x) for x in await self.async_video_in_option("DayNightColor")
        ]                                                
        return values[channel]  

I have no idea why the camera will sometimes not respond with the full expected VideoInOptions API payload. What I typically do to fix this is to reset the firmware to defaults and set it all back up again. So while maybe it can be argued that this is not a bug in the code when the camera API is misbehaving, there really should be a value/range check with a default value created and warning that allows the camera to continue to be set up.

For reference, here is the full response received from the /cgi-bin/configManager.cgi?action=getConfig&name=VideoInOptions command when this error occurs:

table.VideoInOptions[0].AntiFlicker=0
table.VideoInOptions[0].Backlight=0
table.VideoInOptions[0].DoubleExposure=0
table.VideoInOptions[0].ExposureCompensation=50
table.VideoInOptions[0].ExposureIris=50
table.VideoInOptions[0].ExposureMode=0
table.VideoInOptions[0].ExposureValue1=0
table.VideoInOptions[0].ExposureValue2=33.330000
table.VideoInOptions[0].GainMax=50
table.VideoInOptions[0].GainMin=0
table.VideoInOptions[0].GlareInhibition=0
table.VideoInOptions[0].IrisAuto=true
table.VideoInOptions[0].NightOptions.AntiFlicker=0
table.VideoInOptions[0].NightOptions.Backlight=0
table.VideoInOptions[0].NightOptions.DoubleExposure=0
table.VideoInOptions[0].NightOptions.ExposureCompensation=75
table.VideoInOptions[0].NightOptions.ExposureIris=50
table.VideoInOptions[0].NightOptions.ExposureMode=0
table.VideoInOptions[0].NightOptions.ExposureValue1=0
table.VideoInOptions[0].NightOptions.ExposureValue2=33.330000
table.VideoInOptions[0].NightOptions.GainMax=50
table.VideoInOptions[0].NightOptions.GainMin=0
table.VideoInOptions[0].NightOptions.GlareInhibition=0
table.VideoInOptions[0].NightOptions.IrisAuto=true
table.VideoInOptions[0].NightOptions.Profile=3
table.VideoInOptions[0].NightOptions.WideDynamicRange=50
table.VideoInOptions[0].NightOptions.WideDynamicRangeMode=0
table.VideoInOptions[0].NormalOptions.AntiFlicker=0
table.VideoInOptions[0].NormalOptions.Backlight=0
table.VideoInOptions[0].NormalOptions.DoubleExposure=0
table.VideoInOptions[0].NormalOptions.ExposureCompensation=50
table.VideoInOptions[0].NormalOptions.ExposureIris=50
table.VideoInOptions[0].NormalOptions.ExposureMode=8
table.VideoInOptions[0].NormalOptions.ExposureValue1=0
table.VideoInOptions[0].NormalOptions.ExposureValue2=33.330000
table.VideoInOptions[0].NormalOptions.GainMax=50
table.VideoInOptions[0].NormalOptions.GainMin=0
table.VideoInOptions[0].NormalOptions.GlareInhibition=0
table.VideoInOptions[0].NormalOptions.IrisAuto=true
table.VideoInOptions[0].NormalOptions.WideDynamicRange=50
table.VideoInOptions[0].NormalOptions.WideDynamicRangeMode=0
table.VideoInOptions[0].WideDynamicRange=12
table.VideoInOptions[0].WideDynamicRangeMode=1
GaryOkie commented 1 year ago

UPDATE: Overnight a perfectly working different camera suddenly failed with this exact error. 2858 times and counting! It had the exact same reduced response to the VideoInOptions payload as above.


 Logger: homeassistant.helpers.entity
Source: components/amcrest/camera.py:641
First occurred: February 15, 2023 at 8:36:23 PM (2858 occurrences)
Last logged: 8:31:59 AM
Update for camera.frontdrive failed
GaryOkie commented 1 year ago

Problem still occurring with 2 Dahua IPC-T5442T-ZE cameras updated with latest firmware.

Only resolution (other than a software update) is to reset camera to factory defaults and restore a config backup that gets it 90% reconfigured properly.