#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))) ; 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") (write-json (get-pizzas-list) output))))) ; Execute the command specified in the JSON (define (execute-commands input output) (let ((message "")) (let loop-until-eof ((str (read-string 1 input))) (if (eof-object? str) (begin (parse-json message output) (close-input-port input) (close-output-port output)) (begin (set! message (string-append message str)) (loop-until-eof (read-string 1 input))))))) ; 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)