[Custom Component] Tapo: Cameras Control

HomeAssistant - Tapo: Cameras Control

Custom component - Tapo: Cameras Control - to add Tapo cameras into Home Assistant

Installation

Copy contents of custom_components/tapo_control/ to custom_components/tapo_control/ in your Home Assistant config folder.

Installation using HACS

HACS is a community store for Home Assistant. You can install HACS and then install Tapo: Camera Control from the HACS store.

Requirements

Network

Following target TCP ports must be open in firewall for the camera to access your Tapo Camera from Home Assistant:

  • 443 - HTTPS for control of the camera (services)
  • 554 - RTSP to fetch video stream from the camera
  • 2020 - ONVIF to track detected movement via a binary sensor

Usage

Add cameras via Integrations (search for Tapo) in Home Assistant UI.

Cameras are also automatically discovered when they are (re)connected to WIFI.

To add multiple cameras, add integration multiple times.

See examples for lovelace cards or examples for template entities.

Services

This custom component creates:

  • tapo_control.* services to control a camera
  • 2 camera entities, one for HD and one for SD stream
  • 1 binary sensor for motion after the motion is detected for the first time

Use these services in following service calls.

tapo_control.ptz

Pan and tilt camera.

You are also able to use presets and set distance the ptz should travel.

  • entity_id Required: Entity to adjust
  • tilt Optional: Tilt direction. Allowed values: UP, DOWN
  • pan Optional: Pan direction. Allowed values: RIGHT, LEFT
  • preset Optional: PTZ preset ID or a Name. See possible presets in entity attributes.
  • distance Optional: Distance coefficient. Sets how much PTZ should be executed in one request. Allowed values: floating point numbers, 0 to 1
tapo_control.set_privacy_mode

Sets privacy mode.

If privacy mode is turned on, camera does not record anything and does not respond to anything other than turning off privacy mode.

  • entity_id Required: Entity to set privacy mode for
  • privacy_mode Required: Sets privacy mode for camera. Possible values: on, off
tapo_control.set_alarm_mode

Sets alarm mode.

If camera detects motion, it will sound an alarm, blink the LED or both.

  • entity_id Required: Entity to set alarm mode for
  • alarm_mode Required: Sets alarm mode for camera. Possible values: on, off
  • sound Optional: Sets whether the alarm should use sound on motion detected. Possible values: on, off
  • light Optional: Sets whether the alarm should use light on motion detected. Possible values: on, off
tapo_control.set_led_mode

Sets LED mode.

When on, LED is turned on when camera is on.

When off, LED is always off.

  • entity_id Required: Entity to set LED mode for
  • led_mode Required: Sets LED mode for camera. Possible values: on, off
tapo_control.format

Formats SD card of a camera

  • entity_id Required: Entity to format
tapo_control.set_motion_detection_mode

Sets motion detection mode.

Ability to set “high”, “normal” or “low”.

These turn on motion detection and set sensitivity to corresponding values in the app.

Also ability to set to “off”, this turns off motion detection completely.

Turning motion detection off does not affect settings for recordings so you do not need to re-set those unless you open the settings through the Tapo app.

Notice: If you use motion detection triggered recording and you turn off motion recording, it will no longer record!

  • entity_id Required: Entity to set motion detection mode for
  • motion_detection_mode Required: Sets motion detection mode for camera. Possible values: high, normal, low, off
tapo_control.set_auto_track_mode

Warning: This mode is not available in Tapo app and we do not know why. Use at your own risk and please report any success or failures in Home Assistant: Community Forum.

Sets auto track mode.

With this mode, camera will be adjusting ptz to track whatever moving object it sees.

Motion detection setting does not affect this mode.

  • entity_id Required: Entity to set auto track mode for
  • auto_track_mode Required: Sets auto track mode for camera. Possible values: on, off
tapo_control.reboot

Reboots the camera

  • entity_id Required: Entity to reboot
tapo_control.save_preset

Saves the current PTZ position to a preset

  • entity_id Required: Entity to save the preset for
  • name Required: Name of the preset. Cannot be empty or a number
tapo_control.delete_preset

Deletes a preset

  • entity_id Required: Entity to delete the preset for
  • preset Required: PTZ preset ID or a Name. See possible presets in entity attributes
tapo_control.set_day_night_mode

Sets day or night mode

  • entity_id Required: Entity to set day/night mode for
  • day_night_mode Required: Sets day/night mode for camera. Possible values: on, off, auto

Troubleshooting | FAQ

Binary sensor for motion doesn't show up or work

Motion sensor is added only after a motion is detected for the first time.

  • Make sure the camera has motion detection turned on
  • Make sure the camera has privacy mode turned off
  • Make sure the camera can see you and your movement
  • Try walking in front of the camera
  • If above didn’t work, restart the camera and try again

Also make sure that:

  • binary sensor is not disabled via entity, check .storage/core.entity_registry for disabled entities, look for “disabled_by”: “user” on platform “tapo_control”. If it is, remove the whole entity or change to “disabled_by”: null, and restart HASS.
  • binary sensor is enabled in tapo integration options
  • onvif port 2020 on camera is opened
Big delay in camera stream

This is a known issue of Home Assistant.

There is an ability to disable usage of Home Assistant Stream component for the camera, which might lower the delay very significantly at cost of higher CPU usage.

You can choose to disable stream component when adding the camera, or via Options when camera has already been added. This change requires a restart of Home Assistant.

There might be some disadvantages to doing this, like losing option to control playback and a higher CPU usage.
Results depend on your hardware and future Home Assistant updates.

If you disable stream and your hardware is not up to the task, you will get artifacts, bigger delay and freezes.

If you wish, try it out and see what works best for you.

No audio in camera stream

Supported audio codecs in Home Assistant are “aac”, “ac3” and “mp3”.

Tapo Cameras use PCM ALAW (alaw) which is not supported.

More details here.

Supported models

Users reported full functionality with following Tapo Cameras:

  • C100
  • C200
  • C310

The integration should work with any other Tapo Cameras.

If you had success with some other model, please report it via a new issue.

Have a comment or a suggestion?

Please open a new issue, or discuss on Home Assistant: Community Forum.

Join discussion on Discord.

Thank you

Buy Me A Coffee

Disclaimer

This integration is using python module Pytapo which is an unofficial module for achieving interoperability with Tapo cameras.

Author is in no way affiliated with Tp-Link or Tapo.

All the api requests used within the pytapo library are available and published on the internet (examples linked above) and the pytapo module is purely just a wrapper around those https requests.

Author does not guarantee functionality of this integration and is not responsible for any damage.

All product names, trademarks and registered trademarks in this repository, are property of their respective owners.

15 Likes

Spectacular - I have 3 Tapo camera’s (c100, 2 x c200) I’ll be trying this out on tonight. New to this HA lark but will do what I can to help out :slight_smile:

Some help for further development:

This is a Tp-Link C200, basic_info, info, and module_spec:

{

    "device_info": {

        "basic_info": {

            "device_type": "SMART.IPCAMERA",

            "device_model": "C200",

            "device_name": "C200 1.0",

            "device_info": "C200 1.0",

            "hw_version": "1.0",

            "sw_version": "1.0.14 Build 200720 Rel.38552n(4555)",

            "device_alias": "Tapo_Camera_XXXX",

            "features": "3",

            "barcode": "",

            "mac": "AA-BB-CC-DD-EE-00",

            "dev_id": "XXXXXXXXXXXXXXXXX",

            "oem_id": "XXXXXXXXXXXXXXXXXX",

            "hw_desc": "XXXXXXXXXXXXXXXXXXXXXX"

        }

    },

    "error_code": 0

}
{
    "device_info": {
        "info": {
            ".name": "info",
            ".type": "info",
            "device_model": "C200",
            "hw_version": "1.0",
            "fw_description": "C200 1.0",
            "product_id": "00c20000",
            "device_name": "C200 1.0",
            "device_info": "C200 1.0",
            "cur_isp_version": "14",
            "sensor": "SC2335",
            "sw_version": "1.0.14 Build 200720 Rel.38552n(4555)",
            "sys_software_revision": "0x500a0100",
            "sys_software_revision_minor": "0x000e",
            "device_type": "SMART.IPCAMERA",
            "features": "3",
            "domain_name": "tplogin.cn",
            "language": "EN",
            "enable_dns": "1",
            "manufacturer_name": "TP-LINK",
            "friendly_name": "IPC",
            "model_description": "IPC",
            "manufacturer_url": "http://www.tp-link.com",
            "vendor_id": "0x00000001",
            "zone_code": "0x0",
            "roi_reg_num": "1",
            "cover_reg_num": "4",
            "md_reg_num": "32",
            "td_reg_num": "1",
            "plugin_obtain_way": "web",
            "product_type": "ipc",
            "up_fw_shared_prefix": "Tapo_C200v1",
            "unify_firmware_support": "1",
            "isp_version": "14"
        }
    },
    "error_code": 0
}
{

    "function": {

        "module_spec": {

            ".name": "module_spec",

            ".type": "module-spec",

            "app_version": "1.0.0",

            "led": "1",

            "change_password": "1",

            "local_storage": "1",

            "timing_reboot": "1",

            "motor": "1",

            "ota_upgrade": "1",

            "msg_push": "1",

            "msg_alarm": "1",

            "network": [

                "wifi"

            ],

            "events": [

                "motion",

                "tamper"

            ],

            "playback": [

                "local",

                "p2p",

                "relay"

            ],

            "preview": [

                "local",

                "p2p",

                "relay"

            ],

            "video_codec": [

                "h264"

            ],

            "audio": [

                "speaker",

                "microphone"

            ],

            "download": [

                "video"

            ],

            "record_type": [

                "timing",

                "motion"

            ],

            "record_max_slot_cnt": "10",

            "stream_max_sessions": "10",

            "streaming_support_versions": [

                "1.0"

            ],

            "relay_support_versions": [

                "1.3"

            ],

            "p2p_support_versions": [

                "1.1"

            ],

            "device_share": [

                "preview",

                "playback",

                "motor",

                "voice"

            ],

            "msg_alarm_list": [

                "sound",

                "light"

            ],

            "storage_api_version": "2.2",

            "playback_scale": "1",

            "lens_mask": "1",

            "target_track": "1",

            "wireless_hotspot": "1",

            "wifi_connection_info": "1",

            "video_detection_digital_sensitivity": "1",

            "client_info": "1",

            "ssl_cer_version": "1.0",

            "media_encrypt": "1",

            "multi_user": "0",

            "auth_encrypt": "1"

        }

    },

    "error_code": 0

}

This is a Tp-Link C100, basic_info , info , and module_spec :

{

    "device_info": {

        "basic_info": {

            "device_type": "SMART.IPCAMERA",

            "device_model": "C100",

            "device_name": "C100 1.0",

            "device_info": "C100 1.0",

            "hw_version": "1.0",

            "sw_version": "1.0.2 Build 200306 Rel.41295n(4555)",

            "device_alias": "Tapo_Camera_XXXX",

            "features": "3",

            "barcode": "",

            "mac": "AA-BB-CC-DD-EE-00",

            "dev_id": "XXXXXXXXXXXXXXXXX",

            "oem_id": "XXXXXXXXXXXXXXXXXX",

            "hw_desc": "XXXXXXXXXXXXXXXXXXXXXX"

        }

    },

    "error_code": 0

}
{

    "device_info": {

        "info": {

            ".name": "info",

            ".type": "info",

            "device_model": "C100",

            "hw_version": "1.0",

            "fw_description": "C100 1.0",

            "product_id": "00c10000",

            "device_name": "C100 1.0",

            "device_info": "C100 1.0",

            "cur_isp_version": "5",

            "sw_version": "1.0.2 Build 200306 Rel.41295n(4555)",

            "sys_software_revision": "0x500a0100",

            "sys_software_revision_minor": "0x0002",

            "device_type": "SMART.IPCAMERA",

            "features": "3",

            "domain_name": "tplogin.cn",

            "language": "EN",

            "enable_dns": "1",

            "manufacturer_name": "TP-LINK",

            "friendly_name": "IPC",

            "model_description": "IPC",

            "manufacturer_url": "http://www.tp-link.com",

            "vendor_id": "0x00000001",

            "zone_code": "0x0",

            "roi_reg_num": "1",

            "cover_reg_num": "4",

            "md_reg_num": "32",

            "td_reg_num": "1",

            "plugin_obtain_way": "web",

            "product_type": "ipc",

            "up_fw_shared_prefix": "Tapo_C100v1",

            "unify_firmware_support": "1",

            "isp_version": "5"

        }

    },

    "error_code": 0

}
{

    "function": {

        "module_spec": {

            ".name": "module_spec",

            ".type": "module-spec",

            "app_version": "1.0.0",

            "led": "1",

            "change_password": "1",

            "local_storage": "1",

            "timing_reboot": "1",

            "ota_upgrade": "1",

            "msg_push": "1",

            "msg_alarm": "1",

            "network": [

                "wifi"

            ],

            "events": [

                "motion",

                "tamper"

            ],

            "playback": [

                "local",

                "p2p",

                "relay"

            ],

            "preview": [

                "local",

                "p2p",

                "relay"

            ],

            "video_codec": [

                "h264"

            ],

            "audio": [

                "speaker",

                "microphone"

            ],

            "download": [

                "video"

            ],

            "record_type": [

                "timing",

                "motion"

            ],

            "record_max_slot_cnt": "10",

            "stream_max_sessions": "10",

            "streaming_support_versions": [

                "1.0"

            ],

            "relay_support_versions": [

                "1.3"

            ],

            "p2p_support_versions": [

                "1.1"

            ],

            "device_share": [

                "preview",

                "playback",

                "voice"

            ],

            "msg_alarm_list": [

                "sound",

                "light"

            ],

            "storage_api_version": "2.2",

            "playback_scale": "1",

            "lens_mask": "1",

            "wireless_hotspot": "1",

            "wifi_connection_info": "1",

            "video_detection_digital_sensitivity": "1",

            "client_info": "1",

            "ssl_cer_version": "1.0",

            "media_encrypt": "1",

            "multi_user": "0",

            "auth_encrypt": "1"

        }

    },

    "error_code": 0

}

(I haven’t updated the firmware on this one yet.)

1 Like

Version 1.0 has been released!

Initial release of Tapo: Cameras Control

New Features

  • Support for multiple cameras
  • Internal authentication does not expire and works even after reboot of a camera
  • Automatic update of all camera entities
  • Main attributes of camera for every entity, along with preset list
  • Full HACS compatibility

New services

  • tapo_control.ptz
  • tapo_control.set_privacy_mode
  • tapo_control.set_alarm_mode
  • tapo_control.set_led_mode
  • tapo_control.set_motion_detection_mode
  • tapo_control.set_auto_track_mode
  • tapo_control.reboot
  • tapo_control.save_preset
  • tapo_control.delete_preset

Details for services in readme.

Questions? Feedback? Bugs?

If you have any suggestions, questions or bug reports please open a new issue, or discuss on Home Assistant: Community Forum.

3 Likes

WOW! This works great, thank you for your good work!

1 Like

Brilliant work. Thank you

1 Like

VERSION 2.0 :tada:

It has been a few days since the first release, and I feel its a time for version 2.0 which is packed with a lot of awesome new features.

I would like to say special thank you to everyone who reported bugs or joined discussion on Home Assistant: Community Forum

New Features

  • Completely refactored the whole integration. Code is now a lot easier to read, simpler and up to current HASS standards.
  • Set up via Home Assistant Integrations UI, which also means, setup via configuration.yaml is no longer supported.
  • Automatically creates a new device in Home Assistant with its information like firmware, brand, model etc
  • Each device automatically creates 2 entities - HD and SD streams of camera platform
  • Camera stream is now available
  • Ability to format SD card of a camera
  • Better error handling and validation of service calls before they get executed

Minor updates

  • Integration now has an icon, brand and model
  • Added motion_detection and motion_detection_sensitivity attributes
  • Added privacy_mode attribute
  • Added alarm and alarm_mode attributes
  • Added led attribute
  • Added auto_track attribute

Breaking Changes

  • Integration is now set up via UI. You will need to remove tapo_control from configuration.yaml and set up integration using Home Assistant -> Configuration -> Integrations. Just search for tapo and add the cameras.
  • Entities of platform tapo_control are no longer created, camera platform is used instead.
  • Entity names now include _hd or _sd in the name. This does not affect services.
5 Likes

Great work! :pray:
Need to dig up my C200 from the junk again and try this!

Great work! Thank you!:+1:

Thanks for your great work!
How do you view and control your cameras inside the dashboard?

I created switches to use with a picture glance, but maybe there is are ways to optimize this, for example using some kind of joystick instead of switches for ptz.

Here are my switches:

  - platform: template
    switches:
      camera_preset_default:
        value_template: "on"
        unique_id: cam1_preset_default
        turn_on:
          service: tapo_control.ptz
          data_template:
            preset: 1
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            preset: 1
            entity_id: camera.cam1_hd

  - platform: template
    switches:
      camera_preset_down:
        value_template: "on"
        unique_id: cam1_preset_down
        turn_on:
          service: tapo_control.ptz
          data_template:
            preset: 2
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            preset: 2
            entity_id: camera.cam1_hd
            
  - platform: template
    switches:
      camera_preset_up:
        value_template: "on"
        unique_id: cam1_preset_up
        turn_on:
          service: tapo_control.ptz
          data_template:
            preset: 3
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            preset: 3
            entity_id: camera.cam1_hd
            
  - platform: template
    switches:
      camera_up:
        value_template: "on"
        unique_id: cam1_up
        turn_on:
          service: tapo_control.ptz
          data_template:
            tilt: UP
            distance: 0.1
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            tilt: UP
            distance: 0.1
            entity_id: camera.cam1_hd
            
  - platform: template           
    switches:
      camera_down:
        value_template: "on"
        unique_id: cam1_down
        turn_on:
          service: tapo_control.ptz
          data_template:
            tilt: DOWN
            distance: 0.1
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            tilt: DOWN
            distance: 0.1
            entity_id: camera.cam1_hd
            
  - platform: template                    
    switches:
      camera_left:
        value_template: "on"
        unique_id: cam1_left
        turn_on:
          service: tapo_control.ptz
          data_template:
            pan: LEFT
            distance: 0.1
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            pan: LEFT
            distance: 0.1
            entity_id: camera.cam1_hd
   
  - platform: template                  
    switches:
      camera_right:
        unique_id: cam1_right
        value_template: "on"
        turn_on:
          service: tapo_control.ptz
          data_template:
            pan: RIGHT
            distance: 0.1
            entity_id: camera.cam1_hd
        turn_off:
          service: tapo_control.ptz
          data_template:
            pan: RIGHT
            distance: 0.1
            entity_id: camera.cam1_hd
            
            
  - platform: template                  
    switches:
      camera_privacy:
        value_template: "{{ is_state_attr('camera.cam1_hd','privacy_mode' ,'on') }}"
        unique_id: cam1_privacy
        turn_on:
          service: tapo_control.set_privacy_mode
          data_template:
            entity_id: camera.cam1_hd
            privacy_mode: 'on'
        turn_off:
          service: tapo_control.set_privacy_mode
          data_template:
            entity_id: camera.cam1_hd
            privacy_mode: 'off'

I have tried to use the service to toggle privacy mode on and off but can only get it to toggle on
The command for toggle off doesn´t seem to work ?

Trying this via the Developer tools

How are you testing this? The app is buggy, you need to restart it, or not use at all (watch stream in hass instead). See this discussion, maybe you are dealing with the same thing.

1 Like

You can also use something like this:

camera_image: camera.bedroom_hd
camera_view: live
entities:
  - entity: camera.bedroom_hd
    icon: 'mdi:palm-tree'
    tap_action:
      action: call-service
      service: script.set_bedroom_camera_away
  - entity: camera.bedroom_hd
    icon: 'mdi:home'
    tap_action:
      action: call-service
      service: script.set_bedroom_camera_home
hold_action:
  action: call-service
  service: python_script.set_camera
  service_data:
    entity_id: sensor.show_camera
    state: '70'
tap_action:
  action: more-info
title: Bedroom
type: picture-glance

Until someone creates a new lovelace component I think solution like these are the best we can get.

You where right. I was watching in the Tapo app and when restarting the app all was good.

Also checked in Hass and it workes great

1 Like

am I correct in thinking that motion sensing state is not currently supported but camera feeds are? I assume I can combine T:CC with ONVIF to get both. If so what would people recomend as the preferred video source, stream via ONVIF or stream via T:CC?

@JurajNyiri - superb work sir :slight_smile:

Thank you :slight_smile:

Yes you are correct. It is planned for 2.1 as onvif is able to get the status, I should be able to replicate the logic inside this integration.

I have created many more feature requests I plan to implement in the future, I need help with this one specifically.

As in which stream to use, I have just checked onvif integration and internal code works exactly the same.

1 Like

Version 2.1 has been released! :running_man:

New Features

Motion sensor

The first time your camera detects a motion it creates a new binary sensor. This sensor is updated in real time whenever there is a motion to on or off state.
After the next Home Assistant reboot, this sensor is restored with unavailable state until it detects motion again.

Motion sensor should recover from any reboots or disconnects of the camera automatically.

See the new troubleshooting section in readme if you have any questions regarding motion sensor before creating a new issue.

Camera image

Component now also provides an image of the current stream.

It generates it from the current stream on Home Assistant. While this is a common practice in other integrations too, we could do better and get the image directly from the camera instead. See this feature request if you would like to help.

New update coordinator

This release includes a rewrite of how updates are handled, resulting in 2 times reduction of number of requests outgoing camera while not affecting update speed.

Other minor updates

  • support for services camera.disable_motion_detection and camera.enable_motion_detection
  • support for services camera.turn_on camera.turn_off

Final remarks

If you need help…

Please open a new issue or a feature request, or discuss and ask for help on Home Assistant: Community Forum.

If you would like to help…

Join the discussion or see issues marked with help wanted.

There are already some examples going around with requests for more.

I would love to see what people already created with this camera on lovelace, so please open a PR and let’s share!

4 Likes

Created Discord server for support, research and discussion. Feel free to join! :slight_smile:

Would be possible to have those services implemented as entities where possible? Like motion detection being on or off could be a switch and the value would be updated by polling.