[Custom Component] Tapo: Cameras Control

Correct. Although I’ve also executed the command pip3 install ffmpeg and it did not work eventually. I’ve had many problems with HA on Windows, which means I haven’t figured what requirements it needs. So I moved onto Docker, but apparently if you use integrations that need different ports to work (like the HomeKit integration) they do not work even configuring ports and firewalls.
I’ve solved all the problems I had by simply setting up a VM on VirtualBox using HASSIO on my NAS.
Just sharing this to anyone who is struggling with the problems I described. Thanks for your support.

1 Like

Just wanted to say thanks for this! Got my C200 today after a bit of research and glad I can get it all working in HA.

I’m running on a Pi4 and have disabled “stream” as I only have 1 camera and the delay wasn’t really bearable with it on and everything is running fine. I have about 18 containers running on my Pi 4 which idles at around 13% CPU usage, when I access the cameras tab in HA it now shoots up to about 40% which is a fair jump but okay for the time being with one camera! Not sure if there’s a way of just importing it in a normal way outside of the integration that has better performance or not?

I especially like that I can have a privacy button in HA now that turns the camera to a wall and also enables privacy mode, and the inverse when the home alarm is set! Thanks for the work!

1 Like

Hey, with other integrations for stream you will see the same, either a delay or high cpu usage. Solution to that is bumping up the HW to keep up with the cpu requirements.

Version 3.0 :mag: has been released!

Description

This release enables discovery for Tapo cameras.

This feature is now possible thanks to a newly added DHCP Discovery in Home Assistant.

You need to be using Home Assistant version 2021.2 or newer, and have DHCP integration enabled (or be using default_config:).

Your new camera will be automatically discovered when it (re)connects to wifi.

After your camera is discovered, you can configure it directly from Home Assistant Integration page.

New Features

  • Automatic camera discovery
  • Updated Troubleshooting / FAQ with more Q&A
  • Config flow now does a lot more checks and informs user what he needs to do to resolve his issues. Following checks have been added:
    • IP address is not a supported Tapo device
    • Port 443, 554, or 2020 is closed
    • IP address already configured

Breaking changes

None.

2 Likes

Uhm, how exactly did you take the camera offline afterwards? Just removed it in the app? So if you want to make changes to something, you’d have to set it up again?

I’m asking because I’d like to take the camera off the cloud, but would love to preserve the funtionanality of this component. I assumed the component worked though the cloud API, so if I remove the camera from the app, how does HA connect?

Thanks for the great work.

Hey, you can block it via network firewall in your router.

Integration works through local connection, does not use cloud for anything.

Do not remove it from the app, app works also through local if you are on the same network.

Thanks for the details. I will look into that :slight_smile:

Version 3.1 :clock1:

Description

This release adds a possibility to synchronise time with your cameras. This is especially useful when your camera does not have internet access, because the time gets desynchronised fairly quickly.

You will need to enable this feature, by going to your integrations, finding your camera under Tapo integration and opening Options. There will be a new option to Automatically synchronise time.

After turning on this option, camera will now automatically synchronise time on Home Assistant start (or on camera being added) and then every 1 hour.

Breaking changes

None.

3 Likes

Thanks for the great Tapo integration. I love these cameras! I’ve been trying to automate switching on a pan/tilt preset facing the wall and Privacy mode on so everyone knows they’re not being recorded when they’re home. It’s been the only way I can install cameras and I understand why.

I’ve set up a template switch for each camera as follows:

  - platform: template
    switches:
      cam_kitchen_privacy_mode:
        value_template: "{{ is_state_attr('camera.kitchen_hd', 'privacy_mode', 'on') }}"
        turn_on:
        - service: tapo_control.ptz
          data:
            entity_id: camera.kitchen_hd
            preset: 2
        - service: tapo_control.set_privacy_mode
          data:
            entity_id: camera.kitchen_hd
            privacy_mode: 'on'
        turn_off:
        - service: tapo_control.set_privacy_mode
          data:
            entity_id: camera.kitchen_hd
            privacy_mode: 'off'
        - service: tapo_control.ptz
          data:
            entity_id: camera.kitchen_hd
            preset: 1

This works great. Now I wanted to automate setting them back on when we vacate the areas. (asleep or away). So I set an automation up to turn the switches on which works great apart from the rare possibility if one the cameras has been set to privacy mode manually through the app or a toggle on the camera preview. I get this error and the automation/script stops running:

[2981106832] Error: Privacy mode is ON, not able to execute Response:{"error_code": -64324}
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 135, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1445, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 215, in service_handler
    await script_entity.async_turn_on(
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 320, in async_turn_on
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1026, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 242, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 250, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 596, in _async_choose_step
    await self._async_run_script(script)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 670, in _async_run_script
    await self._async_run_long_action(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 419, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1026, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 242, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 250, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 460, in _async_call_service_step
    await self._async_run_long_action(service_task)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 419, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1445, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 215, in service_handler
    await script_entity.async_turn_on(
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 320, in async_turn_on
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1026, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 242, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 250, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 596, in _async_choose_step
    await self._async_run_script(script)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 670, in _async_run_script
    await self._async_run_long_action(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 419, in _async_run_long_action
    long_task.result()
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1026, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 242, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 250, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 457, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1445, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 204, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 593, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 664, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 630, in _handle_entity_call
    await result
  File "/usr/src/homeassistant/homeassistant/components/template/switch.py", line 189, in async_turn_on
    await self._on_script.async_run(context=self._context)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 1026, in async_run
    await asyncio.shield(run.async_run())
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 242, in async_run
    await self._async_step(log_exceptions=False)
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 250, in _async_step
    await getattr(
  File "/usr/src/homeassistant/homeassistant/helpers/script.py", line 457, in _async_call_service_step
    await service_task
  File "/usr/src/homeassistant/homeassistant/core.py", line 1445, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1480, in _execute_service
    await handler.job.target(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 576, in handle_service
    await service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 593, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 664, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 630, in _handle_entity_call
    await result
  File "/config/custom_components/tapo_control/camera.py", line 260, in ptz
    await self.hass.async_add_executor_job(
  File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/local/lib/python3.8/site-packages/pytapo/__init__.py", line 378, in setPreset
    return self.performRequest(
  File "/usr/local/lib/python3.8/site-packages/pytapo/__init__.py", line 104, in performRequest
    raise Exception(
Exception: Error: Privacy mode is ON, not able to execute Response:{"error_code": -64324}

So I’ve just spent a few hours trying to get a script to work, which has been a bit of a nightmare but I think I’ve cracked it, pending some extended testing:

cameras_indoor_privacy_on:
  alias: Cameras Indoor Privacy On
  mode: parallel
  sequence:
    - choose:
      - conditions:
          - condition: state
            entity_id: camera.kitchen_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_kitchen_privacy_mode
          - delay: 10
          - service: script.cameras_indoor_privacy_on
      - conditions:
          - condition: state
            entity_id: camera.bedroom_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_bedroom_privacy_mode
          - delay: 10
          - service: script.cameras_indoor_privacy_on
      - conditions:
          - condition: state
            entity_id: camera.lounge_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_lounge_privacy_mode
  
cameras_indoor_privacy_off:
  alias: Cameras Indoor Privacy Off
  mode: parallel
  sequence:
    - choose:
      - conditions:
          - condition: state
            entity_id: camera.kitchen_hd
            attribute: privacy_mode
            state: 'on'
        sequence:
          - service: switch.turn_off
            entity_id: switch.cam_kitchen_privacy_mode
          - delay: 5
          - service: script.cameras_indoor_privacy_off
      - conditions:
          - condition: state
            entity_id: camera.bedroom_hd
            attribute: privacy_mode
            state: 'on'
        sequence:
          - service: switch.turn_off
            entity_id: switch.cam_bedroom_privacy_mode
          - delay: 5
          - service: script.cameras_indoor_privacy_off
      - conditions:
          - condition: state
            entity_id: camera.lounge_hd
            attribute: privacy_mode
            state: 'on'
        sequence:
          - service: switch.turn_off
            entity_id: switch.cam_lounge_privacy_mode

I tried lots of different things but it seems the privacy on script was taking a while to realise the privacy mode attribute so kept failing. I had to introduce a long delay 5-10s to make sure it didn’t fail. Weirdly I didn’t have the same issue with the off script at 1s delay but I added 5s just to be on the safe side.

I also tried a wait for trigger but this didn’t work for one reason or another:

cameras_indoor_privacy_on:
  alias: Cameras Indoor Privacy On
  mode: parallel
  sequence:
    - choose:
      - conditions:
          - condition: state
            entity_id: camera.kitchen_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_kitchen_privacy_mode
          - wait_for_trigger:
              - platform: state
                entity_id: camera.kitchen_hd
                attribute: privacy_mode
                to: 'off'
          - service: script.cameras_indoor_privacy_on
      - conditions:
          - condition: state
            entity_id: camera.bedroom_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_bedroom_privacy_mode
          - wait_for_trigger:
              - platform: state
                entity_id: camera.bedroom_hd
                attribute: privacy_mode
                to: 'off'
          - service: script.cameras_indoor_privacy_on
      - conditions:
          - condition: state
            entity_id: camera.lounge_hd
            attribute: privacy_mode
            state: 'off'
        sequence:
          - service: switch.turn_on
            entity_id: switch.cam_lounge_privacy_mode

If anyone has any suggestions how I can improve this or maybe if this error can be fixed that would be great!

Hey, that error is a valid error, when you have privacy mode turned on, you are not able to control PTZ and some other functions until the privacy mode is disabled.

Update happens as soon as you trigger any command to camera or every 10 seconds.

If you haven’t yet, check examples for lovelace cards or examples for template entities.

I am doing something similar - automatically turning cameras via ptz and setting privacy when I get home or go away, see https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/blob/e719a75b629e81fc2163d30f47951b814d33ac41/examples/EXAMPLES_LOVELACE.md#picture-glance-with-live-view-and-scripts-tap-and-hold-actions for my usage.

1 Like

Ah ok maybe that error is the switch trying to turn ptz preset on before the camera is out of privacy mode. The problem is that it stops the rest of the script or automation from continuing. I’m doing pretty much the same as you, so you will have the same issue if someone turns on privacy mode before you run set_bedroom_camera_home. I guess for that example it’s not going to happen as you’re away but I wanted it to be foolproof for maybe when I set them to on at night and someone turns the privacy mode back on.

Yes that is true, but I am exposing only those 2 buttons in hass, so there is no way to reach that scenario :slight_smile:

Hello all,
this is a wonderful thread, however I’m not able to customize a Lovelace card with the services created after the installation of the Tapo HACS component. I’d like to inserte glances in my camera view, but no way to get it work.
For example, the tapo_control.ptz works well from Developers Tools -> services, but from a Lovelace card configuration I always get the following error: Visual editor is not supported for this configuration:
The provided value for “entities.0” is not supported by the visual editor. We support (Object<{entity,name,icon,image,secondary_info,format,state_color,tap_action,hold_action,double_tap_action}> | string | Object<{type,name,action_name,tap_action,hold_action,double_tap_action}> | Object<{type,view,dashboard,name,icon,hide_if_unavailable}> | Object<{type,row,conditions}> | Object<{type,style}> | Object<{type,label}> | Object<{type,url,name,icon}> | Object<{type,entities}> | Object<{type,entity,attribute,prefix,suffix,name}> | Object<{type,name,service,icon,action_name,service_data}>) but received ({“entity”:“camera.garage_hd”,“icon”:“mdi:arrow-left-drop-circle-outline”,“tap_action”:{“action”:“call-service”,“service”:“tapo_control.ptz”}}).

I’ve also tried to edit the configuration.yaml, but it seems that entities are not accepted.
I get the following errors when validation the configuration.yaml:

Component error: entities - Integration ‘entities’ not found.
Component error: camera_view - Integration ‘camera_view’ not found.
Component error: camera_image - Integration ‘camera_image’ not found.

Would somebody be so kind to point me where I’m wrong?
Thanks

Hello,

you are mixing configuration.yaml with lovelace stuff. Those are separate systems.
Not everything is supported by visual editor, then you need to edit it through yaml (via UI, not configuration.yaml). That is expected and I get the same, you just need to edit it via yaml, once you save it it should work.

You will need to learn how lovelace works and what configuration is for.

After you are done with that, some working examples for lovelace are listed here: https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/blob/10e95b2b3d6c8595cf20d37f4d9c990fa961a704/examples/EXAMPLES_LOVELACE.md

Thanks Juraj, however this is not fully clear to me. I installed HA Core and from Lovelace I do see the following editor:


The last message refers to YAML editor, but I’m not able to find it.

If you copy the code from post 102 into a blank card (manual) and change ALL the entities to your camera entity it will work…I’ve done it myself.

Also your card is a picture entity and it should be a “picture glance” card

Silly me! It works like a charm…
I’ve always started from a predefined Picture entity card, instead of a manual one.
Thanks Marc, you made my day!

First of all: Greate work on this integration!!!

Can someone help me on this?

The HD preview works for some time and than it break.

“Use Stream from Home Assistant” is disable.
I have Home Assistant in a Intel i5 with 16gb Ram and 256GB SSD, so I don think that the problem is the clock.

I’m getting 2 erros in logs:

Error handling request
1:33:30 – custom_components/tapo_control/camera.py (ERROR)

Logger: aiohttp.server
Source: custom_components/tapo_control/camera.py:209
First occurred: 1:33:30 (1 occurrences)
Last logged: 1:33:30
Error handling request
Traceback (most recent call last):
File “/usr/local/lib/python3.8/site-packages/aiohttp/web_protocol.py”, line 422, in _handle_request
resp = await self._request_handler(request)
File “/usr/local/lib/python3.8/site-packages/aiohttp/web_app.py”, line 499, in _handle
resp = await handler(request)
File “/usr/local/lib/python3.8/site-packages/aiohttp/web_middlewares.py”, line 118, in impl
return await handler(request)
File “/usr/src/homeassistant/homeassistant/components/http/security_filter.py”, line 56, in security_filter_middleware
return await handler(request)
File “/usr/src/homeassistant/homeassistant/components/http/request_context.py”, line 18, in request_context_middleware
return await handler(request)
File “/usr/src/homeassistant/homeassistant/components/http/ban.py”, line 72, in ban_middleware
return await handler(request)
File “/usr/src/homeassistant/homeassistant/components/http/auth.py”, line 127, in auth_middleware
return await handler(request)
File “/usr/src/homeassistant/homeassistant/components/http/view.py”, line 129, in handle
result = await result
File “/usr/src/homeassistant/homeassistant/components/camera/init.py”, line 502, in get
return await self.handle(request, camera)
File “/usr/src/homeassistant/homeassistant/components/camera/init.py”, line 537, in handle
return await camera.handle_async_mjpeg_stream(request)
File “/config/custom_components/tapo_control/camera.py”, line 209, in handle_async_mjpeg_stream
await stream.close()
File “/usr/local/lib/python3.8/site-packages/haffmpeg/core.py”, line 158, in close
await self._loop.run_in_executor(None, _close)
File “/usr/local/lib/python3.8/concurrent/futures/thread.py”, line 57, in run
result = self.fn(*self.args, **self.kwargs)
File “/usr/local/lib/python3.8/site-packages/haffmpeg/core.py”, line 153, in _close
self._proc.stdin.write(b"q")
BrokenPipeError: [Errno 32] Broken pipe

1:15:01 – Tapo: Cameras Control (ERROR) - a mensagem ocorreu pela primeira às 1:13:34 e apareceu 5 vezes

Logger: custom_components.tapo_control
Source: custom_components/tapo_control/init.py:209
Integration: Tapo: Cameras Control (documentation, issues)
First occurred: 1:13:34 (5 occurrences)
Last logged: 1:15:01
Unable to connect to Tapo: Cameras Control controller: HTTPSConnectionPool(host=‘192.168.68.152’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x7f0f00370040>: Failed to establish a new connection: [Errno 113] Host is unreachable’))
Unable to connect to Tapo: Cameras Control controller: HTTPSConnectionPool(host=‘192.168.68.152’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x7f0efd4df5b0>: Failed to establish a new connection: [Errno 113] Host is unreachable’))
Unable to connect to Tapo: Cameras Control controller: HTTPSConnectionPool(host=‘192.168.68.152’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x7f0efc65fbb0>: Failed to establish a new connection: [Errno 113] Host is unreachable’))
Unable to connect to Tapo: Cameras Control controller: HTTPSConnectionPool(host=‘192.168.68.152’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x7f0efc63fe80>: Failed to establish a new connection: [Errno 113] Host is unreachable’))
Unable to connect to Tapo: Cameras Control controller: HTTPSConnectionPool(host=‘192.168.68.152’, port=443): Max retries exceeded with url: / (Caused by NewConnectionError(‘<urllib3.connection.HTTPSConnection object at 0x7f0efcac95e0>: Failed to establish a new connection: [Errno 113] Host is unreachable’))

Hello,

That means your camera went offline. Make sure yo update to latest firmware. If issue persists, check your network connection, restart the camera and try to debug yourself. There’s not much how anyone can help you with this unfortunately.

1 Like