listeningdaemon/visualiser/visualiser.el
2024-11-03 22:18:49 +00:00

389 lines
14 KiB
EmacsLisp

;; visualiser.el
(load-file "~/.emacs.d/elpa/dash-20240510.1327/dash.elc")
(load-file "~/.emacs.d/elpa/mqtt-mode-20180611.1735/mqtt-mode.elc")
(require 'dash)
(require 'mqtt-mode)
(toggle-debug-on-error)
;; directory variables
(defconst graphviz-command "circo")
(defconst graphviz-graph-output-format "svg")
(defconst graphviz-graph-output-dir "graphs/")
(defconst graphviz-image-output-dir (concat graphviz-graph-output-format "s/"))
(defconst snapshot-text-output-dir "snapshots/")
(defconst working-directory "~/Applications/listeningdaemon/visualiser/")
(load-file (concat working-directory "secrets.el"))
;; colors
;; (defconst on-color "black" "The default color for objects which are active")
(defconst off-color "invis" "The default color for objects which are not active")
;; (defvar colors '("orange" "plum"))
;; "colors for the nodes and edges to choose from")
;; (defvar gesture-color (elt colors (random (length colors))) "color to outline objects involved in a gesture")
(defvar on-color "black")
(defvar transform-color "black")
;;; nodes
;; default colors
(defvar fan-one-color off-color)
(defvar fan-two-color off-color)
(defvar radio-one-color off-color)
(defvar lamp-one-color off-color)
(defvar lamp-two-color off-color)
(defvar printer-one-color off-color)
(defvar printer-two-color off-color)
(defvar fan-one-gesture-color fan-one-color)
(defvar fan-two-gesture-color fan-two-color)
(defvar radio-one-gesture-color radio-one-color)
(defvar lamp-one-gesture-color lamp-one-color)
(defvar lamp-two-gesture-color lamp-two-color)
(defvar printer-one-gesture-color printer-one-color)
(defvar printer-two-gesture-color printer-two-color)
;;; edges
;; default colors
(defvar fan-one-fan-two-color off-color)
(defvar fan-one-radio-one-color off-color)
(defvar fan-one-lamp-one-color off-color)
(defvar fan-one-lamp-two-color off-color)
(defvar fan-one-printer-one-color off-color)
(defvar fan-one-printer-two-color off-color)
(defvar fan-two-radio-one-color off-color)
(defvar fan-two-lamp-one-color off-color)
(defvar fan-two-lamp-two-color off-color)
(defvar fan-two-printer-one-color off-color)
(defvar fan-two-printer-two-color off-color)
(defvar radio-one-lamp-one-color off-color)
(defvar radio-one-lamp-two-color off-color)
(defvar radio-one-printer-one-color off-color)
(defvar radio-one-printer-two-color off-color)
(defvar lamp-one-lamp-two-color off-color)
(defvar lamp-one-printer-one-color off-color)
(defvar lamp-one-printer-two-color off-color)
(defvar lamp-two-printer-one-color off-color)
(defvar lamp-two-printer-two-color off-color)
(defvar printer-one-printer-two-color off-color)
(setq snapshot 10000)
(defun clear-graph ()
"Reset the graph to a plain screen"
nil nil
(setq fan-one-color off-color)
(setq fan-two-color off-color)
(setq radio-one-color off-color)
(setq lamp-one-color off-color)
(setq lamp-two-color off-color)
(setq printer-one-color off-color)
(setq printer-two-color off-color)
(setq fan-one-gesture-color fan-one-color)
(setq fan-two-gesture-color fan-two-color)
(setq radio-one-gesture-color radio-one-color)
(setq lamp-one-gesture-color lamp-one-color)
(setq lamp-two-gesture-color lamp-two-color)
(setq printer-one-gesture-color printer-one-color)
(setq printer-two-gesture-color printer-two-color)
;;; edges
;; default colors
(setq fan-one-fan-two-color off-color)
(setq fan-one-radio-one-color off-color)
(setq fan-one-lamp-one-color off-color)
(setq fan-one-lamp-two-color off-color)
(setq fan-one-printer-one-color off-color)
(setq fan-one-printer-two-color off-color)
(setq fan-two-radio-one-color off-color)
(setq fan-two-lamp-one-color off-color)
(setq fan-two-lamp-two-color off-color)
(setq fan-two-printer-one-color off-color)
(setq fan-two-printer-two-color off-color)
(setq radio-one-lamp-one-color off-color)
(setq radio-one-lamp-two-color off-color)
(setq radio-one-printer-one-color off-color)
(setq radio-one-printer-two-color off-color)
(setq lamp-one-lamp-two-color off-color)
(setq lamp-one-printer-one-color off-color)
(setq lamp-one-printer-two-color off-color)
(setq lamp-two-printer-one-color off-color)
(setq lamp-two-printer-two-color off-color)
(setq printer-one-printer-two-color off-color)
(format-graph))
(defun turn-object-on (object)
"Turn an object on"
nil
nil
;; (setq on-color (elt colors (random (length colors))))
(cond ((equal object 'fan-one)
(setq fan-one-color on-color)
(format-graph))
((equal object 'fan-two)
(setq fan-two-color on-color)
(format-graph))
((equal object 'lamp-one)
(setq lamp-one-color on-color)
(format-graph))
((equal object 'lamp-two)
(setq lamp-two-color on-color)
(format-graph))
((equal object 'radio-one)
(setq radio-one-color on-color)
(format-graph))
((equal object 'printer-one)
(setq printer-one-color on-color)
(format-graph))
((equal object 'printer-two)
(setq printer-two-color on-color)
(format-graph))))
(defun turn-object-off (object)
"Turn an object off"
nil
nil
(cond ((equal object 'fan-one)
(setq fan-one-color off-color)
(format-graph))
((equal object 'fan-two)
(setq fan-two-color off-color)
(format-graph))
((equal object 'lamp-one)
(setq lamp-one-color off-color)
(format-graph))
((equal object 'lamp-two)
(setq lamp-two-color off-color)
(format-graph))
((equal object 'radio-one)
(setq radio-one-color off-color)
(format-graph))
((equal object 'printer-one)
(setq printer-one-color off-color)
(format-graph))
((equal object 'printer-two)
(setq printer-one-color off-color)
(format-graph))))
(defun graph-write-file-quietly ()
"Write the graph buffer to a graphviz file quietly"
(let ((inhibit-message t))
(write-file (concat working-directory graphviz-graph-output-dir "graph" (number-to-string snapshot) ".dot") t)))
(defun format-graph-image-numbered ()
"format the numbered image of the graph quietly, for the .gif"
(let ((inhibit-message t))
(shell-command
(concat graphviz-command " -T" graphviz-graph-output-format " "
working-directory graphviz-graph-output-dir (concat "graph" (number-to-string snapshot) ".dot")
" -o "
working-directory graphviz-image-output-dir
(concat "graph" (number-to-string snapshot) "." graphviz-graph-output-format)))))
(defun format-graph-image-main ()
"format the image of the main graph quietly"
nil
nil
(let ((inhibit-message t))
(shell-command
(concat graphviz-command " -T" graphviz-graph-output-format " "
working-directory graphviz-graph-output-dir (concat "graph" (number-to-string snapshot) ".dot")
" -o "
;; working-directory "main." graphviz-graph-output-format
;; output the generated image to /var/www/ so that the webpage stays updated
"/var/www/img/main." graphviz-graph-output-format
))))
(defun format-graph ()
"Series of functions to format the graph to display in the browser
and ultimately turn into a .gif"
nil
nil
;; preprocess graph
(shell-command (concat "cpp -DFAN_ONE=" fan-one-color " "
"-DFAN_TWO=" fan-two-color " "
"-DRADIO_ONE=" radio-one-color " "
"-DLAMP_ONE=" lamp-one-color " "
"-DLAMP_TWO=" lamp-two-color " "
"-DPRINTER_ONE=" printer-one-color " "
"-DPRINTER_TWO=" printer-two-color " "
"-DFAN_ONE_GESTURE=" fan-one-gesture-color " "
"-DFAN_TWO_GESTURE=" fan-two-gesture-color " "
"-DRADIO_ONE_GESTURE=" radio-one-gesture-color " "
"-DLAMP_ONE_GESTURE=" lamp-one-gesture-color " "
"-DLAMP_TWO_GESTURE=" lamp-two-gesture-color " "
"-DPRINTER_ONE_GESTURE=" printer-one-gesture-color " "
"-DPRINTER_TWO_GESTURE=" printer-two-gesture-color " "
"-DFAN_ONE_FAN_TWO=" fan-one-fan-two-color " "
"-DFAN_ONE_RADIO_ONE=" fan-one-radio-one-color " "
"-DFAN_ONE_LAMP_ONE=" fan-one-lamp-one-color " "
"-DFAN_ONE_LAMP_TWO=" fan-one-lamp-two-color " "
"-DFAN_ONE_PRINTER_ONE=" fan-one-printer-one-color " "
"-DFAN_ONE_PRINTER_TWO=" fan-one-printer-two-color " "
"-DFAN_TWO_RADIO_ONE=" fan-two-radio-one-color " "
"-DFAN_TWO_LAMP_ONE=" fan-two-lamp-one-color " "
"-DFAN_TWO_LAMP_TWO=" fan-two-lamp-two-color " "
"-DFAN_TWO_PRINTER_ONE=" fan-two-printer-one-color " "
"-DFAN_TWO_PRINTER_TWO=" fan-two-printer-two-color " "
"-DRADIO_ONE_LAMP_ONE=" radio-one-lamp-one-color " "
"-DRADIO_ONE_LAMP_TWO=" radio-one-lamp-two-color " "
"-DRADIO_ONE_PRINTER_ONE=" radio-one-printer-one-color " "
"-DRADIO_ONE_PRINTER_TWO=" radio-one-printer-two-color " "
"-DLAMP_ONE_LAMP_TWO=" lamp-one-lamp-two-color " "
"-DLAMP_ONE_PRINTER_ONE=" lamp-one-printer-one-color " "
"-DLAMP_ONE_PRINTER_TWO=" lamp-one-printer-two-color " "
"-DLAMP_TWO_PRINTER_ONE=" lamp-two-printer-one-color " "
"-DLAMP_TWO_PRINTER_TWO=" lamp-two-printer-two-color " "
"-DPRINTER_ONE_PRINTER_TWO=" printer-one-printer-two-color " "
working-directory "main.dot")
(concat "graph" (number-to-string snapshot) ".dot") "*Error*")
(switch-to-buffer-other-window
(concat "graph" (number-to-string snapshot) ".dot"))
(set-mark (point))
(forward-line 6)
(kill-region 0 (point) t)
(graph-write-file-quietly)
(format-graph-image-numbered)
(format-graph-image-main)
(setq snapshot (+ snapshot 1)))
(defun write-to-log ; (&optional topic payload &rest string)
(string-to-record)
"record changes in the log, for commentary on the gif"
nil
nil
;; (when (and topic payload)
;; (message "Topic: %s. Payload: %s" topic payload))
(switch-to-buffer "*Logfile*")
(insert (concat "frame: " snapshot ":"))
(newline)
(insert string-to-record)
(newline)
(lambda () "write a file quietly" nil
(let ((inhibit-message t))
(write-file
(concat working-directory snapshot-text-output-dir
"snapshot-" snapshot ".txt"))))
)
;; (illuminate-edges '("transform" "printer" "one" "fan" "two") "1")
(defun illuminate-edges (topic payload)
"Function to illuminate the edges of the graph"
nil
nil
(let ((payload (string-limit payload 1)))
(let ((from-object (string-join (list (cadr topic) (caddr topic)) "-"))
(to-object (string-join (list (cadddr topic) (car (last topic))) "-")))
(when (string-equal payload "1")
(set (intern (concat from-object "-" to-object "-color")) transform-color)
(set (intern (concat to-object "-" from-object "-color")) transform-color))
(when (string-equal payload "0")
(set (intern (concat from-object "-" to-object "-color")) off-color)
(set (intern (concat to-object "-" from-object "-color")) off-color))
(format-graph))))
;; (illuminate-gesture '("main" "gesture" "printer" "one") "0")
;; (illuminate-gesture '("main" "gesture" "printer" "one") "x")
(defun illuminate-gesture (topic payload)
"Function to illuminate the outlines of nodes on the graph"
nil
nil
(let ((payload (string-limit payload 1)))
(let ((gesture-object (string-join (list (elt topic 2) (elt topic 3)) "-")))
;; (write-to-log topic payload)
(if (string-equal payload "0")
(set (intern (concat gesture-object "-gesture-color")) off-color)
(set (intern (concat gesture-object "-color")) off-color)
(set (intern (concat gesture-object "-gesture-color")) on-color))
(format-graph))))
(defun illuminate-nodes (topic payload)
"Function to illuminate the nodes on the graph, a decision tree"
nil
nil
(let ((payload (string-limit payload 1)))
;; (write-to-log topic payload)
(cond ((and (member "fan" topic) (member "one" topic) (string-equal "1" payload))
(turn-object-on 'fan-one)
(message "Fan one turns on"))
((and (member "fan" topic) (member "one" topic) (string-equal "0" payload))
(message "Fan one turns off")
(turn-object-off 'fan-one))
((and (member "fan" topic) (member "two" topic) (string-equal "1" payload))
(message "Fan two turns on")
(turn-object-on 'fan-two))
((and (member "fan" topic) (member "two" topic) (string-equal "0" payload))
(message "Fan two turns off")
(turn-object-off 'fan-two))
((and (member "lamp" topic) (member "one" topic) (string-equal "1" payload))
(message "Lamp one turns on")
(turn-object-on 'lamp-one))
((and (member "lamp" topic) (member "one" topic) (string-equal "0" payload))
(message "Lamp one turns off")
(turn-object-off 'lamp-one))
((and (member "lamp" topic) (member "two" topic) (string-equal "1" payload))
(message "lamp two turns on")
(turn-object-on 'lamp-two))
((and (member "lamp" topic) (member "two" topic) (string-equal "0" payload))
(message "lamp two turns off")
(turn-object-off 'lamp-two))
((and (member "radio" topic) (member "one" topic) (string-equal "1" payload))
(turn-object-on 'radio-one))
((and (member "radio" topic) (member "one" topic) (string-equal "0" payload))
(turn-object-off 'radio-one))
((and (member "printer" topic) (member "one" topic) (string-equal "2" payload))
(turn-object-on 'printer-one))
((and (member "printer" topic) (member "one" topic) (string-equal "1" payload))
(turn-object-on 'printer-one))
((and (member "printer" topic) (member "one" topic) (string-equal "0" payload))
(turn-object-off 'printer-one))
((and (member "printer" topic) (member "two" topic) (string-equal "2" payload))
(turn-object-on 'printer-two))
((and (member "printer" topic) (member "two" topic) (string-equal "1" payload))
(turn-object-on 'printer-two))
((and (member "printer" topic) (member "two" topic) (string-equal "0" payload))
(turn-object-off 'printer-two)))))
;; printers
(add-to-list 'mqtt-message-receive-functions
(lambda (msg)
"Functions to execute on recieving a message"
nil
(let ((m (string-split msg " ")))
(let ((msg-car (car m))
(payload (cdr m)))
(let ((topic (string-split msg-car "/")))
(cond ((member "transform" topic)
(illuminate-edges topic (car payload)))
((and (member "main" topic) (member "start" topic))
(clear-graph))
((and (member "main" topic) (member "gesture" topic))
(illuminate-gesture topic (car payload)))
((member "main" topic)
(illuminate-nodes topic (car payload)))
))))))
(format-graph)
(mqtt-start-consumer)