* Autodidactism at 700nm ** Bootstrapping #+BEGIN_SRC elisp (let* ((args '("-J-Dclojure.server.repl={:port,9457,:accept,clojure.core.server/repl}")) (clojure-program "clojure") (buffer (get-buffer-create "*clojure*")) (proc-alive (comint-check-proc buffer)) (process (get-buffer-process buffer))) (unless proc-alive (with-current-buffer buffer (apply 'make-comint-in-buffer "Clojure" buffer clojure-program nil args))) (when buffer (pop-to-buffer buffer))) #+END_SRC #+BEGIN_SRC elisp (defun org-babel-execute:clojure (body params) "Execute a block of clojure code with org-babel." (message "executing Foma source code block %s" body) (org-babel-eval "nc localhost 9457" body)) #+END_SRC : org-babel-execute:clojure #+BEGIN_SRC clojure (future (with-open [sock (java.net.ServerSocket. 32466)] (loop [] (try (with-open [s (.accept sock) i (clojure.lang.LineNumberingPushbackReader. ((requiring-resolve 'clojure.java.io/reader) (.getInputStream s))) o ((requiring-resolve 'clojure.java.io/writer) (.getOutputStream s))] (binding [*in* i ,*out* o] ((requiring-resolve 'clojure.main/repl) :prompt (constantly nil)))) (catch Throwable t (prn t))) (recur)))) #+END_SRC : #object[clojure.core$future_call$reify__8544 0x730278dc {:status :pending, :val nil}] #+BEGIN_SRC elisp (defun org-babel-execute:clojure (body params) "Execute a block of clojure code with org-babel." (message "executing Foma source code block %s" body) (org-babel-eval "nc localhost 32466" body)) #+END_SRC : org-babel-execute:clojure ** Motivation Every home automation project eventually needs to control devices that use an infrared remote. I have arrived that place. For some devices there are lists of IR codes, numeric values and combined with some timing information describe how to pulse an ir led on and off to send commands to a device, available online. But luckily for me I am having trouble finding IR codes for some of my devices so I get to do this from scratch. This involves setting up an IR receiver, and recording what it receives for different button presses on remotes. In my case what I get back is something like: ^{:nextjournal.clerk/visibility {:code :hide}} [9136 4429 599 479 595 492 613 503 616 1581 588 534 597 493 598 1594 587 503 616 495 595 497 576 539 595 1584 579 1613 615 506 580 502 588 525 600 1581 580 518 609 507 596 1580 593 558 569 471 619 495 576 1623 605 521 570 494 594 527 596 494 596 493 578 517 611 503 596 498 595] This list of numbers that a receiver reports for a single button press is a _message_. Buttons on a remote will (usually) result in different messages. A message from the remote to the device tells the device to do something. Different messages usually tell it to do different things. I can take this list of numbers and feed it backout through an IR emitter to send the message to a device. Remote cloned, job done. But this long list of numbers is annoying to work with, and depending on the remote you can easily end up with 50+ of these lists per remote. Each number in theory has the range of unsigned 16 bit number, so two bytes per for storage. And I want to to reprogram my IR emitter on the fly. That is a lot of data to be pushing into a poor little microntroller over a bluetooth radio. Ideally I should be able to factor out commonality in these messages to reduce their size, doing some kind of domain specific compression. There is a lot of noise is these numbers. So before attempting any kind of more succint encoding of the information, I need to remove the noise so the messages will _compress_ better. Removing noise will make redundancy more evident. I can use some structural knowledge of how these IR messages tend to work to make a best guess at the amount of noise. After removing the noise I can derive the _alphabet_ of _symbols_ that each remote uses to write it's messages, and generate an efficient binary encoding for that alphabet. To do this I'll need a nice representive sample of messages from the target remote: #+BEGIN_SRC clojure (defn foo [x] (inc x)) #+END_SRC : #'user/foo
Generated At 2023-06-06T19:01:59-0700 original