Tapo P100 Smart Plug Controller
PlugP100 is an asynchronous Python library designed to control TP-Link Tapo P100, P105, P110, L900, L920, and similar smart devices locally. It provides a simple API for common operations like turning devices on/off, checking status, and accessing energy monitoring data where available. The current stable version is 5.1.7, with active development on version 6.x indicating a potential upcoming major release with significant changes.
Common errors
-
RuntimeWarning: coroutine '...' was never awaited
cause Attempting to call an asynchronous function (like `plug.login()`, `plug.turn_on()`) without using the `await` keyword, or not running the top-level async function with `asyncio.run()`.fixPrefix all calls to asynchronous methods with `await` (e.g., `await plug.login()`) and ensure your main application entry point is `asyncio.run(your_async_main_function())`. -
plugp100.common.exceptions.TapoError: Handshake failed
cause The library failed to establish a secure connection or authenticate with the Tapo device, typically due to an incorrect IP address, an invalid Tapo account email, or an incorrect Tapo account password.fixDouble-check the IP address of your Tapo device, ensure the email and password match your Tapo account credentials, and confirm the device is powered on and accessible on your local network. -
ModuleNotFoundError: No module named 'plugp100'
cause The `plugp100` library has not been installed in your current Python environment.fixInstall the library using pip: `pip install plugp100`. -
AttributeError: 'DeviceInfo' object has no attribute 'current_power'
cause You are trying to access an attribute, like `current_power` or `today_energy`, from a `DeviceInfo` object that was returned by a device that does not support energy monitoring (e.g., a P100 plug).fixCheck your device model. If it's a P100, it doesn't support energy monitoring. If it's a P110 or P105, ensure you are calling the correct energy monitoring methods (e.g., `plug.get_current_energy_usage()` or `plug.get_month_energy_usage()`) as these details are not typically part of the basic `DeviceInfo`.
Warnings
- breaking Version 6.0.0, currently in development, is expected to introduce breaking changes to the API. Users should consult the release notes when upgrading from 5.x to 6.x to adapt their code.
- gotcha The `plugp100` library is built entirely on `asyncio`. All interactions with Tapo devices require `await` calls within an `async` function and must be run within an `asyncio` event loop.
- gotcha Authentication errors, specifically `TapoError: Handshake failed`, are common if the IP address, username (Tapo account email), or password for your device is incorrect or if the device is unreachable.
- gotcha Not all Tapo devices or models support every feature. For example, some plugs (like P100) do not provide energy monitoring data, while others (like P110, P105) do. Attempting to access unsupported features may raise errors or return empty data.
Install
-
pip install plugp100
Imports
- PlugP100
from plugp100.api.plug_device import PlugP100
- TapoError
from plugp100.common.exceptions import TapoError
Quickstart
import asyncio
import os
from plugp100.api.plug_device import PlugP100
from plugp100.common.exceptions import TapoError
async def main():
# It's recommended to use environment variables for sensitive data
ip_address = os.environ.get("TAPO_IP", "192.168.1.100") # Replace with your device IP
username = os.environ.get("TAPO_USERNAME", "your_tapo_email@example.com") # Your Tapo account email
password = os.environ.get("TAPO_PASSWORD", "YourTapoPassword") # Your Tapo account password
if not all([ip_address, username, password]):
print("Please set TAPO_IP, TAPO_USERNAME, and TAPO_PASSWORD environment variables.")
return
# Initialize the device client
plug = PlugP100(ip_address, username, password)
try:
# Authenticate with the device
await plug.login()
print(f"Successfully logged in to Tapo device at {ip_address}")
# Get device information
device_info = await plug.get_device_info()
print(f"Device Model: {device_info.model}")
print(f"Device Name: {device_info.device_name}")
print(f"Device is currently {'On' if device_info.device_on else 'Off'}")
# Toggle the plug's power state
if device_info.device_on:
print("Turning off the device...")
await plug.turn_off()
else:
print("Turning on the device...")
await plug.turn_on()
# Get updated device info to confirm state change
device_info_updated = await plug.get_device_info()
print(f"Device is now {'On' if device_info_updated.device_on else 'Off'}")
# Example for P110/P105 with energy monitoring (uncomment if applicable)
# if hasattr(plug, 'get_current_energy_usage'):
# energy_usage = await plug.get_current_energy_usage()
# print(f"Current Power: {energy_usage.current_power} mW")
except TapoError as e:
print(f"Tapo device error: {e}")
except Exception as e:
print(f"An unexpected error occurred: {e}")
finally:
# Ensure the session is properly closed
if plug.is_logged_in: # Check if plug is still logged in before attempting logout
await plug.logout()
print("Logged out from Tapo device.")
if __name__ == "__main__":
asyncio.run(main())