Tapo C310 person detection sensor

Hello.
Can someone help me how to get binary sensor person detection in Tapo c310 integration.
The motion sensor works great but detects everything. Thank you

This request is also outstanding in the HACS-based Tapo integration
awaiting for someone to spend time on it.

hey guys, I recently started using Home assistant and connected my C310 ending at the point you guys at.
But I’m slightly confused as they already implemented the “Person Detection” mode but there is no sensors for this to also push a notifcation to the Logbook

Am I missing something to add the sensor? Been trying to manipulate the Motion Entity ID to Person detection but it seems to have no affect.

Hope anyone found a work around.

Regards

This is motion detection
there is an added feature of ‘person’ detection

There is a settings option for “motion” and “person” detection. But sadly on the settings option you can receive on your phone Tapo app then.

Anyways, has anyone of you a work around to save the record on your Server once the motion sensor was triggered? Since the person detection isn’t available as alert yet I assume its only doable for motion.

Would highly appreciate.

Using Home assistant on Proxmox

1 Like

Same here with C320WS and C110 cams: person detection works like a charm in Tapo app, but I have a LOT of false alarms in HASS - based on the standard motion detection onvif event.

Shadows in the daytime, tiny bugs at night
 completely unuseable for automation.

  • I also started the trial period of Tap Care service to check if they have any kind of notification (e-mail or something), but I can’t see any.

  • I tried to use my Synology NVR’s person detection feature, but it needs at least a 25fps stream to work - what a shame that tapo cameras are maximized in 15


So it doesn’t work either :frowning:

I’m not in app development and packet capturing techniques, but what if one just installs Tapo app in an android emulator and monitors the communication between Tapo app and the cameras/servers?

Anyone tried this?
Or is this kind of reverse engineering a completely bad direction?

Any help appreciated!

Hi all. For what it’s worth, here’s my apporach to getting HA alerts when a person is detected (I have a TP-Link Tapo C320W camerag). My camera only tells me about motion detections, not any other detections. This approach is a bit bare, but it works:

High level overview:
I use a python script to poll my camera for all events that occured, filter for the “person detected” event and send a message to HA using MQTT.

The approach:

  • Make sure you have a MQTT broker running
  • Here’s a nifty method (from the pytapo library, bless their souls) that allows you to read all events from your Tapo Camera that occured between two timeframes.
  • Use a python script to poll the camera events and match on the “person detection” alarm type
  • Use AppDaemon to run the python script (or another way if you have one, but just make sure that the script can access your network)
  • Send a MQTT message whenever the “person detected” event happened.

The code

Be sure to to install the pytapo and paho-mqtt libraries.

here’s the code:

import appdaemon.plugins.hass.hassapi as hass
from paho.mqtt import client as mqtt
from pytapo import Tapo
from datetime import datetime
import time
import json

TRANSPORT = "tcp"
BROKER_ADDRESS = "your-broker-ip"
BROKER_PORT = 1883
BROKER_USERNAME = "broker-username"
BROKER_PASSWORD = "broker-password"
PERSON_DETECTED_ALARM_TYPE = 6
# See https://github.com/JurajNyiri/pytapo/blob/2a28236dfd885947d93f6a98ac1b10cdb0b731d4/pytapo/__init__.py#L677
# To check that `6` is also your camera's `person detected` alarm type, open a python shell, run the code to
# instantiate a tapo client (see code below), let your camera detect a person, call the
# tapo_client.getEvents(startTime=now - 60*10) to see the events for the past 10 minutes and check the last
# event's alarm type ID

ENTITY_ID = "tap_camera" # Give your entity a name
TOPIC= "tapo/person_detected" # change this to your liking
DISCOVERY_TOPIC = f"homeassistant/binary_sensor/{ENTITY_ID}/config"

CAMERA_IP = "camera ip" # make sure this is static
CAMERA_USERNAME = "camera-username"
CAMERA_PASSWORD = "the-camera-password"
INTERVAL_SEC = 5

BIRTH_TOPIC = f"homeassistant/binary_sensor/{ENTITY_ID}/status"
BIRTH_PAYLOAD = "online"
WILL_TOPIC = f"homeassistant/binary_sensor/{ENTITY_ID}/status"
WILL_PAYLOAD = "offline"
UNIQUE_ID = "3e73ef97-470b-5555-6666-f0b59d0552ce" # You can use another unique id here as well, just make sure is
# doesn't change

class TapoEventListener(hass.Hass):

    def initialize(self):
        self.mqtt_client = None
        self.tapo_client = None
        self._setup_clients()
        self._enter_loop()

    def _send_message(self, client, message):
        client.publish(TOPIC, message)

    def _publish_discovery(self, client):
        discovery_payload = {
            "name": "Person Detected",
            "state_topic": TOPIC,
            "payload_on": "detected",
            "payload_off": "clear",
            "device_class": "motion",
            "unique_id": UNIQUE_ID,
            "object_id": UNIQUE_ID,
        }
        # Publish the discovery message to the discovery topic
        client.publish(DISCOVERY_TOPIC, json.dumps(discovery_payload), retain=True)

    def _setup_clients(self):
        # MQTT
        self.log("Creating MQTT client...")
        self.mqtt_client = mqtt.Client()
        self.mqtt_client.username_pw_set(BROKER_USERNAME, BROKER_PASSWORD)
        self.log("Setting will message...")
        self.mqtt_client.will_set(WILL_TOPIC, WILL_PAYLOAD, qos=1, retain=True)
        self.log("Connecting...")
        self.mqtt_client.connect(BROKER_ADDRESS, BROKER_PORT)
        self.log("Publishing discovery payload...")
        self._publish_discovery(self.mqtt_client)
        self.log("Sending birth message...")
        self.mqtt_client.publish(BIRTH_TOPIC, BIRTH_PAYLOAD, qos=1, retain=True)

        # Camera
        self.log("Creating Tapo Camera client...")
        self.tapo_client = Tapo(CAMERA_IP, user=CAMERA_USERNAME, password=CAMERA_PASSWORD)


    def _enter_loop(self):
        self.log("Entering loop...")
        now = int(datetime.timestamp(datetime.now()))
        self.tapo_client.getEvents(startTime=now - INTERVAL_SEC)
        try:
            while True:
                person_detected = False
                events = self.tapo_client.getEvents(startTime=now - INTERVAL_SEC)
                self.mqtt_client.reconnect()
                for event in events:
                    alarm_type = event["alarm_type"]
                    if alarm_type == PERSON_DETECTED_ALARM_TYPE:
                        self.log(f"Person detected!")
                        person_detected = True
                        self._send_message(self.mqtt_client, message="detected")
                        break
                if not person_detected:
                    self._send_message(self.mqtt_client, message="clear")

                time.sleep(INTERVAL_SEC)
                now = int(datetime.timestamp(datetime.now()))
        except Exception as e:
            self.log(f"An error occured:\nError:{e}.\nExiting")
            exit(1)

A few notes:

  • I do not know if the Tapo Camera’s API has a rate limit, but I guess there is one. Have no idea what it is, so be careful with the INTERVAL_SEC variable.
  • This script was not tested rigorously. Any suggested improvements are super welcome.
  • Notifications through HA is obviously not as snappy as those from the Tapo app, but there’s max INTERVAL_SEC ± 1 sec delay from detection to notification.

P.S
If you want to make this robust against camera reboots, you’ll have to update the loop by swapping the while and try-except blocks. Something like:

while True:
    try:
        person_detected = False
        events = self.tapo_client.getEvents(startTime=now - INTERVAL_SEC)
        self.log(f"Events: {events}")
        self.mqtt_client.reconnect()
        for event in events:
            alarm_type = event["alarm_type"]
            if alarm_type == PERSON_DETECTED_ALARM_TYPE:
                self.log(f"Person detected!")
                person_detected = True
                self._send_message(self.mqtt_client, message="detected")
                break
        if not person_detected:
            self._send_message(self.mqtt_client, message="clear")
    except Exception as e:
        self.log(f"An error occured:\nError:{e}")
1 Like

Is there a solution for this?

Thank you Chris, you’re awesome!!! :fist_right: :fist_left:
Clearly, pytapo library is the solution.

Which worked for me:
When HA receives a motion detection event from the Tapo camera, I simply run this code from shell (get_detection_type.py):

from pytapo import Tapo
from datetime import datetime

INTERVAL_SEC = 60 # get the most recent alarm from the last 60 seconds
tapo = Tapo("camera ip","camera user","camera password")
tapo_info = tapo.getEvents(int(datetime.timestamp(datetime.now())) - INTERVAL_SEC)
if len(tapo_info)==0:
	print("0")
else:
	print(tapo_info[0].get("alarm_type"))

It returns a numeric value (detection type):

  • 0: No Detection (in the time given interval)
  • 2: Motion Detected
  • 4: Line-Crossing Detected
  • 5: Area Intrusion Detected
  • 6: Person Detected
  • 8: Vehicle Detected

I run my automated tasks according to the answer - simple and works like a charm!

Thanks again!!! :pray: :pray: :pray:

UPDATE:

I also created my own rest sensor (in configuration.yaml):

sensor:
  - platform: rest
    resource: http://myserver/tapo/detection_type.php
    unique_id: dtype
    name: detection_type

The simple http based endpoint (detection_type.php):

<?php

	$command = "python3 get_detection_type.py 2>&1";
	$out = shell_exec($command);
	echo $out;

?>


and finally!

The working detection_type sensor of my Tapo camera:

The default scan_interval in RESTful API is 30s, so HA reads the rest sensor every 30 seconds - it’s obviously not necessary to refresh the sensor at all, it only changes when we get a motion event from the camera, so we can call it manually, but it’s good to know that it works without issues, seems the Tapo API doesn’t have a strict(?) rate limit.


1 Like

Hey., thanks for the update and does this work with both your camera types?

Just tested and yes, it also works!

FYI: if you keep getting “Invalid authentication data” messages from the c110, use this login method, it solved the problem for me:

use “admin” username and your cloud password

1 Like

Tried using your approach but I’m getting the following exception:
Any ideas? tapo.getBasicInfo() for example works, I’m using a Tapo C320WS

Traceback (most recent call last): File “/var/www/html/get_detection_type.py”, line 13, in tapo_info = tapo.getEvents(int(datetime.timestamp(datetime.now())) - INTERVAL_SEC) File “/usr/local/lib/python3.9/dist-packages/pytapo/init.py”, line 688, in getEvents responseData = self.executeFunction( File “/usr/local/lib/python3.9/dist-packages/pytapo/init.py”, line 510, in executeFunction raise Exception( Exception: Error: -71114, Response: {“method”: “searchDetectionList”, “result”: {}, “error_code”: -71114}

I was in the same situation as you and I was going crazy. The solution is to put an SD card in the camera!

Nice!

This works without internet connection in the camera?