1
0
Fork 0

add tapo cli

This commit is contained in:
Maurice Debray 2026-02-10 16:30:26 +01:00
parent ea3f8f01bb
commit efbd8d26f7
7 changed files with 166 additions and 25 deletions

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
/serve/config.txt
/logs
.env

15
nix/lon.lock Normal file
View file

@ -0,0 +1,15 @@
{
"version": "1",
"sources": {
"nixpkgs": {
"type": "GitHub",
"fetchType": "tarball",
"owner": "NixOS",
"repo": "nixpkgs",
"branch": "nixos-unstable",
"revision": "d6c71932130818840fc8fe9509cf50be8c64634f",
"url": "https://github.com/NixOS/nixpkgs/archive/d6c71932130818840fc8fe9509cf50be8c64634f.tar.gz",
"hash": "sha256-ub1gpAONMFsT/GU2hV6ZWJjur8rJ6kKxdm9IlCT0j84="
}
}
}

53
nix/lon.nix Normal file
View file

@ -0,0 +1,53 @@
# Generated by lon. Do not modify!
let
lock = builtins.fromJSON (builtins.readFile ./lon.lock);
# Override with a path defined in an environment variable. If no variable is
# set, the original path is used.
overrideFromEnv =
name: path:
let
replacement = builtins.getEnv "LON_OVERRIDE_${name}";
in
if replacement == "" then
path
else
# this turns the string into an actual Nix path (for both absolute and
# relative paths)
if builtins.substring 0 1 replacement == "/" then
/. + replacement
else
/. + builtins.getEnv "PWD" + "/${replacement}";
fetchSource =
args@{ fetchType, ... }:
if fetchType == "git" then
builtins.fetchGit (
{
url = args.url;
ref = args.branch;
rev = args.revision;
narHash = args.hash;
submodules = args.submodules;
}
// (
if args ? lastModified then
{
inherit (args) lastModified;
shallow = true;
}
else
{ }
)
)
else if fetchType == "tarball" then
builtins.fetchTarball {
url = args.url;
sha256 = args.hash;
}
else
builtins.throw "Unsupported source type ${fetchType}";
in
builtins.mapAttrs (name: args: overrideFromEnv name (fetchSource args)) lock.sources

46
nix/tapo.nix Normal file
View file

@ -0,0 +1,46 @@
{
lib,
rustPlatform,
buildPythonPackage,
maturin,
fetchFromGitHub,
}:
buildPythonPackage rec {
pname = "tapo";
version = "0.8.8";
pyproject = true;
src = fetchFromGitHub {
owner = "mihai-dinculescu";
repo = "tapo";
rev = "v${version}";
hash = "sha256-cVrD2XfS3Oum0DL9DYQfnNN6WKyjSiy94Vj+sUMmbcc=";
};
nativeBuildInputs = [
rustPlatform.cargoSetupHook
rustPlatform.maturinBuildHook
];
sourceRoot = "${src.name}/tapo-py";
cargoRoot = "../";
env = {
CARGO_TARGET_DIR = "./target";
};
cargoDeps = rustPlatform.fetchCargoVendor {
inherit pname version src;
hash = "sha256-Klr3rx1zYcul1gPz6H+d5idHlNJQB3SuY5nZlXwHFmY=";
};
meta = {
description = "Unofficial Tapo API Client. Works with TP-Link Tapo smart devices. Tested with light bulbs (L510, L520, L530, L535, L610, L630), light strips (L900, L920, L930), plugs (P100, P105, P110, P110M, P115), power strips (P300, P304M, P316M), hubs (H100), switches (S200B) and sensors (KE100, T100, T110, T300, T310, T315";
homepage = "https://github.com/mihai-dinculescu/tapo";
changelog = "https://github.com/mihai-dinculescu/tapo/blob/${src.rev}/CHANGELOG.md";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ ];
mainProgram = "tapo";
};
}

47
powercut.py Normal file
View file

@ -0,0 +1,47 @@
import asyncio
import os
import shutil
import sys
import time
from datetime import datetime
from pathlib import Path
import tapo
from dotenv import load_dotenv
from scapy.all import ICMP, IP, sr
load_dotenv()
tapo_username = os.getenv("TAPO_USERNAME")
tapo_password = os.getenv("TAPO_PASSWORD")
tapoip = "10.1.1.79"
async def powercycle():
tapoapi = tapo.ApiClient(tapo_username, tapo_password)
tapoplug = await tapoapi.p100(tapoip)
await tapoplug.off()
await asyncio.sleep(1)
await tapoplug.on()
asyncio.run(powercycle())
print("sleeping for 80s, then ping until up")
time.sleep(1)
while True:
ans, unans = sr(IP(dst="10.1.1.79") / ICMP(), verbose=False)
if len(ans) > 0:
break
print("Collecting :")
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + "-powercut"
log_dir = Path("./logs") / timestamp
log_dir.mkdir(parents=True, exist_ok=True)
shutil.copy(Path(sys.argv[0]), log_dir / sys.argv[0])
print(" - [x] script.py")

View file

@ -1,24 +0,0 @@
#!/usr/bin/env bash
echo "sleeping for 80s, then ping until up"
sleep 80
while true;
do
if ping -w 1 -c 1 192.168.42.6 > /dev/null; then
break
fi
done
echo "collecting logs"
dir="./logs/$(date +"%Y%m%d_%H%M%S")-powercut"
mkdir -p "$dir"
touch "$dir/powercut"
cp ./powercut.sh "$dir"
echo "finished"

View file

@ -1,10 +1,13 @@
{ pkgs ? import <nixpkgs> {} }:
{ pkgs ? import (import ./nix/lon.nix).nixpkgs {} }:
pkgs.mkShell {
name = "junos-testing";
packages = [
pkgs.d2
pkgs.lon
(pkgs.python3.withPackages (p: [
(p.callPackage ./nix/tapo.nix {})
p.scapy
p.python-dotenv
p.tqdm
p.ipython
p.libpcap