64 lines
2.4 KiB
Racket
64 lines
2.4 KiB
Racket
#lang racket
|
|
|
|
(require racket/tcp)
|
|
(require json)
|
|
|
|
(define serial-port-device "/dev/ttyUSB0")
|
|
(define port 4444)
|
|
(define hostname "127.0.0.1")
|
|
|
|
; Return a list of pizzas from the local file
|
|
(define (get-pizzas-list)
|
|
(let ((file (open-input-file "pizza_list.json")))
|
|
(read-json file)))
|
|
|
|
; Send the pizza list as a JSON, prepending it with 4 bytes that contain the list length
|
|
(define (send-pizzas-list output)
|
|
(let ((pizzas-list (get-pizzas-list)))
|
|
(write-bytes (integer->integer-bytes (bytes-length (jsexpr->bytes pizzas-list)) 4 #f) output)
|
|
(write-json pizzas-list output)))
|
|
|
|
; Print the to-print string on the printer
|
|
; TODO add synchronization to avoid race conditions
|
|
(define (printer-print to-print)
|
|
(let ((file (open-output-file serial-port-device #:exists 'append)))
|
|
(display (string-replace to-print "\n" "\n\n") file) ; always add an extra newline because the printer is a little messed up
|
|
(close-output-port file)))
|
|
|
|
; Format the pizzas array from the JSON in a human-readable way
|
|
(define (format-pizza pizzas-list)
|
|
(let ((str ""))
|
|
(for-each (lambda (pizza-hashmap)
|
|
(set! str (string-append str (format "~a : ~s\n" (hash-ref pizza-hashmap 'quantity) (hash-ref pizza-hashmap 'name)))))
|
|
pizzas-list)
|
|
str))
|
|
|
|
; Parse the commands given in the JSON
|
|
(define (parse-json message output)
|
|
(let ((parsed-json (with-input-from-string message (lambda () (read-json))))) ; parse the JSON
|
|
(case (hash-ref parsed-json 'command)
|
|
(("print") (printer-print (hash-ref parsed-json 'text)))
|
|
(("pizza") (printer-print (format-pizza (hash-ref parsed-json 'pizzas))))
|
|
(("get-pizzas") (send-pizzas-list output))
|
|
(else (displayln "Unknown command")))))
|
|
|
|
; Parse the JSON and execute the command specified in it
|
|
;
|
|
; Each message starts with the length of the JSON object, put into the first 4 bytes
|
|
(define (execute-commands input output)
|
|
; read the first 4 bytes, little-endian, unsigned
|
|
(let ((message-length (integer-bytes->integer (read-bytes 4 input) #f)))
|
|
(parse-json (bytes->string/utf-8 (read-bytes message-length input)) output)
|
|
(close-input-port input)
|
|
(close-output-port output)))
|
|
|
|
; Wait on a port and spawn new threads on each connection
|
|
(define (wait-for-connection)
|
|
(let ((listener (tcp-listen port 4 #t hostname)))
|
|
(let infinite-loop ()
|
|
(let-values (((input output) (tcp-accept listener)))
|
|
(thread (lambda () (execute-commands input output)))
|
|
(infinite-loop)))))
|
|
|
|
(wait-for-connection)
|