Emacs creando un widget para controlar mi enchufe inteligente

A lo largo de los años he ido automatizando mi casa, y unos de los dispositivos que más uso es un enchufe inteligente. Para controlarlos uso scripts o la aplicación de SmartThings. Pero me he dado cuenta que me resultaría más cómodo tener un widget en Emacs. Así que me he puesto a ello.

Y este es el resultado.

  • Cuando pulso Enter sobre la bola de color, o hago clic con el ratón, se enciende o apaga el enchufe.
  • Muestra visualmente su estado: Rojo si esta apagado y verde si esta encendido.
  • Se ejecuta en un buffer independiente.
  • Uso herramientas nativas de Emacs, sin dependencias externas.

Es fantástico lo que puedes lograr con Emacs.

Primero debes ser consciente que yo estoy usando un enchufe inteligente compatible con SmartThings, y que además tengo instalado el cliente de SmartThings en mi sistema con la identificación configurada. Quiero decir que ya tengo un comando que me permite obtener el estado del enchufe y otro que me permite cambiarlo. Es un requisito previo e indispensable.

Con ello creo una función que me indique el estado actual de uno de mis enchufes. Lo necesitaremos para que el widget se inicie con el estado correcto.

(defun status-plug ()
  "Get the status of the plug."
  (interactive)
  (let* ((response (json-parse-string (shell-command-to-string "smartthings devices:status xxxxxxxxxxxxxxxxxxx")))
     (status (gethash "value" (gethash "switch" (gethash "switch" (gethash "main" (gethash "components" (json-parse-string (shell-command-to-string "/home/andros/applications/smartthings devices:status xxxxxxxxxxxxxxxxx")))))))))
    (string= status "on")))

Devolverá t si el enchufe está encendido y nil si está apagado.

Ahora creo una función que me permita cambiar el estado del enchufe.

(defun turn-plug (state)
  "Turn the plug on or off."
  (interactive)
  (shell-command (concat "smartthings devices:commands xxxxxxxxxxxxxxxxx switch:" (if state "on" "off"))))

Si state es t encenderá el enchufe, si es nil lo apagará.

Ahora creo un widget con un switch que me permita controlar el enchufe.

  (defvar plug-on "🟢")
  (defvar plug-off "🔴")


  (widget-create 'toggle
         :help-echo "Plug control"
         :on plug-on
         :on-glyph '
         :off plug-off
         :off-glyph '
         :value (status-plug)
         :notify (lambda (widget &rest ignore)
               (turn-plug (widget-value widget))))

Si quieres aprender más sobre los widgets disponibles, puedes realizar mi curso gratuito sobre crear interfaces gráficas en Emacs. O leer la documentación oficial sobre widget.

Finalmente creo un fichero, llamado plug-controller.el que me permita lanzar el widget con todo lo anterior.

;; -*- coding: utf-8 -*-
;; Imports
(require 'widget)

(eval-when-compile
  (require 'wid-edit))

;; Variables
(defvar buffer-name "*Plug controller*")

;; Functions
(defun status-plug ()
  "Get the status of the plug."
  (interactive)
  (let* ((response (json-parse-string (shell-command-to-string "smartthings devices:status xxxxxxxxxxxxxxxxxxx")))
     (status (gethash "value" (gethash "switch" (gethash "switch" (gethash "main" (gethash "components" (json-parse-string (shell-command-to-string "smartthings devices:status xxxxxxxxxxxxxxxxx")))))))))
    (string= status "on")))

(defun turn-plug (state)
  "Turn the plug on or off."
  (interactive)
  (shell-command (concat "smartthings devices:commands xxxxxxxxxxxxxxxxx switch:" (if state "on" "off"))))

(defun plug-controller ()
  "Make widgets for the main layout."
  (interactive)
  ;; Create the buffer
  (switch-to-buffer buffer-name)
  ;; Clear the buffer
  (kill-all-local-variables)
  (let ((inhibit-read-only t))
    (erase-buffer))
  (remove-overlays)
  ;; Title
  (widget-insert "Monitor")
  ;; Widget
  (widget-insert "\n\n🔌 Plug control: ")
  (defvar plug-on "🟢")
  (defvar plug-off "🔴")
  (widget-create 'toggle
         :help-echo "Plug control"
         :on plug-on
         :on-glyph '
         :off plug-off
         :off-glyph '
         :value (status-plug)
         :notify (lambda (widget &rest ignore)
               (turn-plug (widget-value widget))))
  ;; Display the buffer
  (use-local-map widget-keymap)
  (widget-setup)
  ;; Focus on the first link
  (widget-forward 1))

Para lanzarlo usa M-x plug-controller.

Y ya tienes un widget para controlar tu enchufe inteligente desde Emacs.

This work is under a Attribution-NonCommercial-NoDerivatives 4.0 International license.

Will you buy me a coffee?

You can use the terminal.

ssh customer@andros.dev -p 5555

Written by Andros Fenollosa

November 12, 2024

3 min of reading

You may also like