forked from exciting-io/printer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
pi-printer.rb
149 lines (126 loc) · 3.08 KB
/
pi-printer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#!/usr/bin/env ruby
require 'securerandom'
require 'net/http'
require 'serialport'
require 'pi_piper'
class PiPrinter
POLLING_DELAY = 10 # seconds
ID_PATH = "id.txt"
SERVER = "printer.exciting.io" # change this if connecting to your own server
PRINTER_TYPE = "A2-raw"
VERSION = "1.0.0"
def initialize(serial_port: "/dev/ttyAMA0")
debug "Starting printer"
reset_leds
@all_leds.map(&:on)
@serial_port = serial_port
generate_id unless id
reset_download
sleep(1)
@all_leds.map(&:off)
end
def run
debug "Printer ID: #{id}"
loop do
if download_waiting?
if button_pressed?
print_data
end
else
check_for_download
sleep(POLLING_DELAY) unless download_waiting?
end
end
end
private
def id
@id ||= File.exist?(ID_PATH) && File.read(ID_PATH)
end
def generate_id
@id = SecureRandom.hex(8)
File.open(ID_PATH, "w") { |f| f.write @id }
end
def check_for_download
@activity_led.on
debug "Checking for download"
uri = URI("http:https://#{SERVER}/printer/#{id}")
req = Net::HTTP::Get.new(uri)
Net::HTTP.start(uri.host, uri.port) do |http|
request = Net::HTTP::Get.new(uri)
request['Accept'] = "application/vnd.exciting.printer.#{PRINTER_TYPE}"
request['X-Printer-Version'] = VERSION
@data = StringIO.new
http.request(request) do |response|
response.read_body do |chunk|
@data.write(chunk)
end
end
@activity_led.off
end
@data.rewind
@download = @data.read
if @download.length > 0
debug "Downloaded #{@download.length} bytes; saving"
File.open('last-print.data', 'w') { |f| f.write @download }
@success_led.on
end
rescue => e
@activity_led.off
flash(@error_led, 5)
end
def download_waiting?
end
def button_pressed?
true # hard coded until GPIO integration of buttons
end
def print_data
# stream data over serial connection
debug "Printing #{@download.bytes.length} bytes to printer"
serial.write(@download)
reset_download
@success_led.off
end
def reset_download
@download = ''
end
def reset_leds
@error_led, @activity_led, @success_led = [22,23,24].map do |pin|
File.open("/sys/class/gpio/unexport", "w") { |f| f.write(pin) } rescue nil
PiPiper::Pin.new(pin: pin, direction: :out)
end
@all_leds = [@error_led, @activity_led, @success_led]
end
def serial
@serial ||= begin
data_bits, stop_bits, baud = 8, 1, 19200
parity = SerialPort::NONE
serial = SerialPort.new(@serial_port, 19200, data_bits, stop_bits, parity)
serial.sync = true
serial
end
end
def debug(message)
STDOUT.puts "#{Time.now}: #{message}"
STDOUT.flush
end
def flash(led, times)
times.times do
led.on
sleep(0.3)
led.off
sleep(0.3)
end
sleep(1)
end
end
if __FILE__ == $0
loop do
begin
PiPrinter.new.run
rescue => e
puts "Exception while running: #{e}"
puts e.backtrace.join("\n")
end
end
end