[Custom Component] Tapo: Cameras Control

Uncheck this in Integration options on the latest version (just released 2.4.1).


Configuration -> Integrations -> Tapo Cameras Control -> Choose entity -> Options

You should get very similar playback to ffmpeg with that disabled, but your CPU usage will be higher.

Make sure to restart after unchecking and saving.

1 Like

Yeah same as ffmpeg. Gonna try to live with the stream from HA instead of ffmpeg and see. Since Iā€™m not always looking at my cameras, a bit more CPU shouldnā€™t be an issue ^^ā€™

Whatever works for you :slight_smile:

Just to clarify, these are the results you are seeing right?

  • Using stream: Low cpu usage
  • Not using stream (using ffmpeg): High cpu usage

Yup exactly. This may not be an issue when using a bigger CPU like a NUC or a server though.

1 Like

Itā€™s like this man can read my mind:

I gave up trying to link my C200 to HA after I saw that I could only get a still image in HA and nothing else (like ptz or motion detection).

I just came across this project, will definitely give this a try.

Thanks a lot for putting effort into this @JurajNyiri ! It looks very promising and complete :+1:

2 Likes

Great job @JurajNyiri
I have low CPU usage with my intel NUC, but it seems I have less video quality.

1 Like

If we want to switch back from FFMPEG via the Integrations panel we must first killall ffmpeg for the integration to be able to validate the user/pass otherwise we cannot change it backā€¦ just a heads up or even YRMV (maybe just my setup).

On an i5 intel laptop running hass in docker FFMPEG was using 4 cores at 50% for 3 Taposā€¦ for me not worth it for 5 seconds of latency so I went back to non-FFMPEG.

Thank you so much for this Integration too! It was the reason I bought these too!

1 Like

Hey sorry everyone I keep having the same problem, Iā€™ve followed the guide but I cannot get a feed from the camera, it keeps saying Inactive in the image entity, if I use with vlc rtsp://USER:PASSWORD@IP:554/stream1 it works fine. Oddly the motion entity (binary_sensor.mymotiondetectorrule_cell_motion_detection) auto-installed by the integration gets movement if I put my hand in front of the lens but canā€™t get feed. Any ideas?

Hey, are there any errors in log?

Iā€™ve deleted the log file and started HA again, this is all is shows by filtering the camera word in the log file:

2021-01-24 09:34:02 INFO (SyncWorker_3) [homeassistant.loader] Loaded camera from homeassistant.components.camera
2021-01-24 09:34:03 INFO (MainThread) [homeassistant.setup] Setting up camera
2021-01-24 09:34:03 INFO (MainThread) [homeassistant.setup] Setup of domain camera took 0.1 seconds
2021-01-24 09:34:04 INFO (MainThread) [homeassistant.components.camera] Setting up camera.onvif
2021-01-24 09:34:04 INFO (MainThread) [homeassistant.components.camera] Not adding entity Lounge Camera - minorStream because it's disabled
2021-01-24 09:34:07 INFO (MainThread) [homeassistant.components.camera] Setting up camera.tapo_control
2021-01-24 09:34:03 WARNING (MainThread) [haffmpeg.tools] Error starting FFmpeg.
2021-01-24 09:35:10 ERROR (MainThread) [haffmpeg.core] FFmpeg fails [WinError 2] Impossibile trovare il file specificato (Unable to find)
Traceback (most recent call last):
  File "C:\Users\root\AppData\Roaming\.homeassistant\deps\Python38\site-packages\haffmpeg\core.py", line 136, in open
    self._proc = await self._loop.run_in_executor(None, proc_func)
  File "C:\Users\root\AppData\Local\Programs\Python\Python38-32\lib\concurrent\futures\thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "C:\Users\root\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "C:\Users\root\AppData\Local\Programs\Python\Python38-32\lib\subprocess.py", line 1307, in _execute_child
    hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] Impossibile trovare il file specificato
2021-01-24 09:35:10 WARNING (MainThread) [haffmpeg.tools] Error starting FFmpeg.

Last exception keeps going over and over again in the logfile.
Iā€™m quite new to HA but I suppose ffmpeg is what I need to play the camera feed. Donā€™t actually know how to fix this. Running Core on Windows.

This is an error with your setup, you need to make sure that ffmpeg is installed on your environment.

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!