20-sep: Protocolo apagado final con Home Assistant + comandos voz Alexa
This commit is contained in:
137
scripts/protocolo_apagado_final.py
Normal file
137
scripts/protocolo_apagado_final.py
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
"""
|
||||||
|
Protocolo de apagado completo del PC usando HOME ASSISTANT + COMANDOS DE VOZ ALEXA.
|
||||||
|
|
||||||
|
Pasos:
|
||||||
|
1. Cerrar ventanas abiertas
|
||||||
|
2. Apagar luces Alexa via comandos de voz: "apaga barras" y "apaga cuartillo"
|
||||||
|
3. Apagar pantalla (Tapo via tunel RPi)
|
||||||
|
4. Shutdown del PC en 10 segundos
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python protocolo_apagado_final.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Fix encoding para Windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import codecs
|
||||||
|
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
|
||||||
|
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')
|
||||||
|
|
||||||
|
# Cargar variables de entorno locales (.env de biblioteca_negocio_prolongo)
|
||||||
|
dotenv_path = r"C:\Users\juanm\Documents\GitHub\biblioteca_negocio_prolongo\.env"
|
||||||
|
load_dotenv(dotenv_path)
|
||||||
|
|
||||||
|
def cerrar_ventanas():
|
||||||
|
"""Cierra todas las ventanas excepto terminal/OpenCode"""
|
||||||
|
print("1. Cerrando ventanas abiertas (excepto terminal de OpenCode)...")
|
||||||
|
ps_command = """
|
||||||
|
$procesos = Get-Process | Where-Object { $_.MainWindowHandle -ne 0 -and $_.ProcessName -notmatch 'OpenCode|WindowsTerminal|cmd|powershell|Code|conhost' }
|
||||||
|
foreach ($p in $procesos) {
|
||||||
|
try {
|
||||||
|
$p.CloseMainWindow() | Out-Null
|
||||||
|
Start-Sleep -Milliseconds 200
|
||||||
|
if (-not $p.HasExited) { $p.Kill() }
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
subprocess.run(["powershell", "-Command", ps_command], capture_output=True)
|
||||||
|
print(" [OK] Ventanas cerradas.")
|
||||||
|
|
||||||
|
def apagar_luces_alexa():
|
||||||
|
"""Apaga las luces 'barras' y 'cuartillo' via comandos de voz a Alexa"""
|
||||||
|
print("2. Apagando luces de Alexa via comandos de voz (barras + cuartillo)...")
|
||||||
|
|
||||||
|
url = os.getenv("HOMEASSISTANT_URL")
|
||||||
|
token = os.getenv("HOMEASSISTANT_TOKEN")
|
||||||
|
|
||||||
|
if not url or not token:
|
||||||
|
print(" [ERROR] Falta HOMEASSISTANT_URL o HOMEASSISTANT_TOKEN en .env")
|
||||||
|
return
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Entity ID del Echo Dot principal
|
||||||
|
echo_entity = "media_player.echo_dot_de_nahid"
|
||||||
|
|
||||||
|
comandos = [
|
||||||
|
("barras", "apaga barras"),
|
||||||
|
("cuartillo", "apaga cuartillo")
|
||||||
|
]
|
||||||
|
|
||||||
|
for nombre, comando in comandos:
|
||||||
|
data = {
|
||||||
|
"entity_id": echo_entity,
|
||||||
|
"media_content_type": "custom",
|
||||||
|
"media_content_id": comando
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{url}/api/services/media_player/play_media",
|
||||||
|
headers=headers,
|
||||||
|
json=data,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f" [OK] Comando enviado: '{comando}'")
|
||||||
|
else:
|
||||||
|
print(f" [ERROR] Error HTTP {response.status_code} al apagar '{nombre}'")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [ERROR] Error al apagar '{nombre}': {e}")
|
||||||
|
|
||||||
|
def apagar_pantalla_tapo():
|
||||||
|
"""Apaga el enchufe Tapo de la pantalla via tunel RPi"""
|
||||||
|
print("3. Apagando pantalla (Tapo) via tunel RPi...")
|
||||||
|
|
||||||
|
# Script Python que se ejecutara en la RPi
|
||||||
|
tapo_script = r"""from PyP100 import PyP100
|
||||||
|
p100 = PyP100.P100('192.168.50.224', 'hermes211@gmail.com', 'Nelo@36666')
|
||||||
|
p100.handshake()
|
||||||
|
p100.login()
|
||||||
|
p100.turnOff()"""
|
||||||
|
|
||||||
|
# Comando SSH en dos saltos: local -> VPS -> RPi
|
||||||
|
cmd = [
|
||||||
|
"ssh", "-i", r"C:\Users\juanm\Documents\GitHub\contabo",
|
||||||
|
"root@185.187.169.109",
|
||||||
|
f"ssh -i /root/.ssh/pi_deploy -p 2222 -o StrictHostKeyChecking=no pi@127.0.0.1 'python3 -c \"{tapo_script}\"'"
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = subprocess.run(cmd, capture_output=True, timeout=15, text=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(" [OK] Pantalla apagada.")
|
||||||
|
else:
|
||||||
|
print(f" [ERROR] Error al apagar pantalla (codigo {result.returncode})")
|
||||||
|
if result.stderr:
|
||||||
|
print(f" stderr: {result.stderr.strip()}")
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print(" [ERROR] Timeout al apagar pantalla (>15s)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [ERROR] Excepcion al apagar pantalla: {e}")
|
||||||
|
|
||||||
|
def shutdown_pc():
|
||||||
|
"""Apaga el PC en 10 segundos"""
|
||||||
|
print("4. Apagando el PC en 10 segundos...")
|
||||||
|
os.system("shutdown /s /t 10")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print(" PROTOCOLO DE APAGADO COMPLETO")
|
||||||
|
print("=" * 60)
|
||||||
|
cerrar_ventanas()
|
||||||
|
apagar_luces_alexa()
|
||||||
|
apagar_pantalla_tapo()
|
||||||
|
shutdown_pc()
|
||||||
|
print("=" * 60)
|
||||||
|
print(" PROTOCOLO COMPLETADO")
|
||||||
|
print("=" * 60)
|
||||||
145
scripts/protocolo_apagado_final_test.py
Normal file
145
scripts/protocolo_apagado_final_test.py
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
"""
|
||||||
|
Protocolo de apagado completo (VERSION TEST - SIN SHUTDOWN).
|
||||||
|
|
||||||
|
Pasos:
|
||||||
|
1. Cerrar ventanas abiertas
|
||||||
|
2. Apagar luces Alexa via comandos de voz: "apaga barras" y "apaga cuartillo"
|
||||||
|
3. Apagar pantalla (Tapo via tunel RPi)
|
||||||
|
4. [COMENTADO] Shutdown del PC
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python protocolo_apagado_final_test.py
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Fix encoding para Windows
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import codecs
|
||||||
|
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
|
||||||
|
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')
|
||||||
|
|
||||||
|
# Cargar variables de entorno locales (.env de biblioteca_negocio_prolongo)
|
||||||
|
dotenv_path = r"C:\Users\juanm\Documents\GitHub\biblioteca_negocio_prolongo\.env"
|
||||||
|
load_dotenv(dotenv_path)
|
||||||
|
|
||||||
|
def cerrar_ventanas():
|
||||||
|
"""Cierra todas las ventanas excepto terminal/OpenCode"""
|
||||||
|
print("1. Cerrando ventanas abiertas (excepto terminal de OpenCode)...")
|
||||||
|
ps_command = """
|
||||||
|
$procesos = Get-Process | Where-Object { $_.MainWindowHandle -ne 0 -and $_.ProcessName -notmatch 'OpenCode|WindowsTerminal|cmd|powershell|Code|conhost' }
|
||||||
|
foreach ($p in $procesos) {
|
||||||
|
try {
|
||||||
|
$p.CloseMainWindow() | Out-Null
|
||||||
|
Start-Sleep -Milliseconds 200
|
||||||
|
if (-not $p.HasExited) { $p.Kill() }
|
||||||
|
} catch {}
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
subprocess.run(["powershell", "-Command", ps_command], capture_output=True)
|
||||||
|
print(" [OK] Ventanas cerradas.")
|
||||||
|
|
||||||
|
def apagar_luces_alexa():
|
||||||
|
"""Apaga las luces 'barras' y 'cuartillo' via comandos de voz a Alexa"""
|
||||||
|
print("2. Apagando luces de Alexa via comandos de voz (barras + cuartillo)...")
|
||||||
|
|
||||||
|
url = os.getenv("HOMEASSISTANT_URL")
|
||||||
|
token = os.getenv("HOMEASSISTANT_TOKEN")
|
||||||
|
|
||||||
|
if not url or not token:
|
||||||
|
print(" [ERROR] Falta HOMEASSISTANT_URL o HOMEASSISTANT_TOKEN en .env")
|
||||||
|
return
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Entity ID del Echo Dot principal
|
||||||
|
echo_entity = "media_player.echo_dot_de_nahid"
|
||||||
|
|
||||||
|
comandos = [
|
||||||
|
("barras", "apaga barras"),
|
||||||
|
("cuartillo", "apaga cuartillo")
|
||||||
|
]
|
||||||
|
|
||||||
|
for nombre, comando in comandos:
|
||||||
|
data = {
|
||||||
|
"entity_id": echo_entity,
|
||||||
|
"media_content_type": "custom",
|
||||||
|
"media_content_id": comando
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{url}/api/services/media_player/play_media",
|
||||||
|
headers=headers,
|
||||||
|
json=data,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f" [OK] Comando enviado: '{comando}'")
|
||||||
|
else:
|
||||||
|
print(f" [ERROR] Error HTTP {response.status_code} al apagar '{nombre}'")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [ERROR] Error al apagar '{nombre}': {e}")
|
||||||
|
|
||||||
|
def apagar_pantalla_tapo():
|
||||||
|
"""Apaga el enchufe Tapo de la pantalla via tunel RPi"""
|
||||||
|
print("3. Apagando pantalla (Tapo) via tunel RPi...")
|
||||||
|
|
||||||
|
# Crear script temporal en VPS y ejecutar via RPi
|
||||||
|
script_content = """from PyP100 import PyP100
|
||||||
|
p100 = PyP100.P100('192.168.50.224', 'hermes211@gmail.com', 'Nelo@36666')
|
||||||
|
p100.handshake()
|
||||||
|
p100.login()
|
||||||
|
p100.turnOff()"""
|
||||||
|
|
||||||
|
# Paso 1: Crear script en VPS
|
||||||
|
cmd1 = [
|
||||||
|
"ssh", "-i", r"C:\Users\juanm\Documents\GitHub\contabo",
|
||||||
|
"root@185.187.169.109",
|
||||||
|
f"echo '{script_content}' > /tmp/tapo_off.py"
|
||||||
|
]
|
||||||
|
|
||||||
|
# Paso 2: Copiar a RPi y ejecutar
|
||||||
|
cmd2 = [
|
||||||
|
"ssh", "-i", r"C:\Users\juanm\Documents\GitHub\contabo",
|
||||||
|
"root@185.187.169.109",
|
||||||
|
"scp -i /root/.ssh/pi_deploy -P 2222 -o StrictHostKeyChecking=no /tmp/tapo_off.py pi@127.0.0.1:/tmp/ && ssh -i /root/.ssh/pi_deploy -p 2222 -o StrictHostKeyChecking=no pi@127.0.0.1 'python3 /tmp/tapo_off.py'"
|
||||||
|
]
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.run(cmd1, capture_output=True, timeout=5, text=True)
|
||||||
|
result = subprocess.run(cmd2, capture_output=True, timeout=15, text=True)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print(" [OK] Pantalla apagada.")
|
||||||
|
else:
|
||||||
|
print(f" [ERROR] Error al apagar pantalla (codigo {result.returncode})")
|
||||||
|
if result.stderr:
|
||||||
|
print(f" stderr: {result.stderr.strip()}")
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print(" [ERROR] Timeout al apagar pantalla (>15s)")
|
||||||
|
except Exception as e:
|
||||||
|
print(f" [ERROR] Excepcion al apagar pantalla: {e}")
|
||||||
|
|
||||||
|
def shutdown_pc():
|
||||||
|
"""NO APAGA el PC en modo test"""
|
||||||
|
print("4. [TEST MODE] Shutdown deshabilitado para pruebas.")
|
||||||
|
print(" En produccion ejecutaria: shutdown /s /t 10")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print(" PROTOCOLO DE APAGADO (TEST - SIN SHUTDOWN)")
|
||||||
|
print("=" * 60)
|
||||||
|
cerrar_ventanas()
|
||||||
|
apagar_luces_alexa()
|
||||||
|
apagar_pantalla_tapo()
|
||||||
|
shutdown_pc()
|
||||||
|
print("=" * 60)
|
||||||
|
print(" PROTOCOLO COMPLETADO")
|
||||||
|
print("=" * 60)
|
||||||
88
scripts/test_alexa_voz.py
Normal file
88
scripts/test_alexa_voz.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
"""
|
||||||
|
Test de comandos de voz a Alexa via Home Assistant.
|
||||||
|
|
||||||
|
Uso:
|
||||||
|
python test_alexa_voz.py "apaga barras"
|
||||||
|
python test_alexa_voz.py "apaga cuartillo"
|
||||||
|
python test_alexa_voz.py "enciende barras"
|
||||||
|
"""
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
# Fix encoding
|
||||||
|
if sys.platform == 'win32':
|
||||||
|
import codecs
|
||||||
|
sys.stdout = codecs.getwriter('utf-8')(sys.stdout.buffer, 'strict')
|
||||||
|
sys.stderr = codecs.getwriter('utf-8')(sys.stderr.buffer, 'strict')
|
||||||
|
|
||||||
|
dotenv_path = r"C:\Users\juanm\Documents\GitHub\biblioteca_negocio_prolongo\.env"
|
||||||
|
load_dotenv(dotenv_path)
|
||||||
|
|
||||||
|
def enviar_comando_voz(echo_entity, comando):
|
||||||
|
"""Envia un comando de voz a un dispositivo Echo"""
|
||||||
|
url = os.getenv("HOMEASSISTANT_URL")
|
||||||
|
token = os.getenv("HOMEASSISTANT_TOKEN")
|
||||||
|
|
||||||
|
if not url or not token:
|
||||||
|
print("[ERROR] Falta HOMEASSISTANT_URL o HOMEASSISTANT_TOKEN en .env")
|
||||||
|
return False
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {token}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
|
||||||
|
data = {
|
||||||
|
"entity_id": echo_entity,
|
||||||
|
"media_content_type": "custom",
|
||||||
|
"media_content_id": comando
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = requests.post(
|
||||||
|
f"{url}/api/services/media_player/play_media",
|
||||||
|
headers=headers,
|
||||||
|
json=data,
|
||||||
|
timeout=10
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
print(f"[OK] Comando enviado: '{comando}' -> {echo_entity}")
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
print(f"[ERROR] HTTP {response.status_code}: {response.text}")
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[ERROR] {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def main():
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Uso: python test_alexa_voz.py \"comando\"")
|
||||||
|
print()
|
||||||
|
print("Ejemplos:")
|
||||||
|
print(" python test_alexa_voz.py \"apaga barras\"")
|
||||||
|
print(" python test_alexa_voz.py \"apaga cuartillo\"")
|
||||||
|
print(" python test_alexa_voz.py \"enciende barras\"")
|
||||||
|
return
|
||||||
|
|
||||||
|
comando = sys.argv[1]
|
||||||
|
|
||||||
|
# Probamos con el Echo Dot principal
|
||||||
|
echo_entity = "media_player.echo_dot_de_nahid"
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
print(f" ENVIANDO COMANDO DE VOZ A ALEXA")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"Comando: {comando}")
|
||||||
|
print(f"Echo: {echo_entity}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
enviar_comando_voz(echo_entity, comando)
|
||||||
|
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user