389 lines
14 KiB
EmacsLisp
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)
|