-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathmain-knob.py
executable file
·222 lines (174 loc) · 6.39 KB
/
main-knob.py
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
# From picamera2 examples: capture_jpeg.py
#!/usr/bin/python3
# Capture a JPEG while still running in the preview mode. When you
# capture to a file, the return value is the metadata for that image.
import time, requests, signal, os
from picamera2 import Picamera2, Preview
from gpiozero import LED, Button
from Adafruit_Thermal import *
from wraptext import *
from datetime import datetime
#instantiate printer
printer = Adafruit_Thermal('/dev/serial0', 9600, timeout=5)
#instantiate camera
picam2 = Picamera2()
# start camera
picam2.start()
time.sleep(2) # warmup period since first few frames are often poor quality
# NEXT 3 LINES FOR DEBUGGING: computer preview of image
# Slows down the program considerably
# Only use for checking camera object
# TODO: WHY DOES THIS PREVIEW NOT WORK OVER SSH?
#preview_config = picam2.create_preview_configuration(main={"size": (800, 600)})
#picam2.configure(preview_config)
#picam2.start_preview(Preview.QTGL)
#instantiate buttons
shutter_button = Button(16)
power_button = Button(26, hold_time = 2)
# different rotary switch knob positions
knob1 = Button(17)
knob2 = Button(27)
knob3 = Button(22)
knob4 = Button(5)
knob5 = Button(6)
knob6 = Button(13)
knob7 = Button(19)
knob8 = Button(25)
knob9 = Button(24)
knob10 = Button(23)
current_knob = None
#############################
# CORE PHOTO-TO-POEM FUNCTION
#############################
def take_photo_and_print_poem():
# Take photo & save it
metadata = picam2.capture_file('/home/carolynz/CamTest/images/image.jpg')
# FOR DEBUGGING: print metadata
#print(metadata)
# TODO? Takes a photo and saves to memory
#image = picam2.capture_image()
#print(image)
# Close camera -- commented out because this can only happen at end of program
# picam2.close()
# FOR DEBUGGING: note that image has been saved
print('----- SUCCESS: image saved locally')
#######################
# Receipt printer:
# Date/time/location frontmatter
#######################
# Note: important to put this section as high up as possible
# to get printing to happen quickly & improve perceived performance
# Get current date+time -- will use for printing and file naming
now = datetime.now()
# Format printed datetime like:
# Jan 1, 2023
# 8:11 PM
printer.justify('C') # center align header text
date_string = now.strftime('%b %-d, %Y')
time_string = now.strftime('%-I:%M %p')
printer.println('\n')
printer.println(date_string)
printer.println(time_string)
# TODO: get and print location
# optical spacing adjustments
printer.setLineHeight(56) # I want something slightly taller than 1 row
printer.println()
printer.setLineHeight() # Reset to default (32)
printer.println("`'. .'`'. .'`'. .'`'. .'`'. .'`")
printer.println(" ` ` ` ` ` ")
#########################
# Send saved image to API
#########################
api_url = 'https://poetry-camera.carozee.repl.co/pic_to_poem'
# OLD: get PIL Image object from memory
# files = {'file': image}
# Read file that was saved to disk as a byte array
with open('/home/carolynz/CamTest/images/image.jpg', 'rb') as f:
byte_im = f.read()
# prep format for API call
image_filename = 'rpi-' + now.strftime('%Y-%m-%d-at-%I.%M-%p')
files = {'file': (image_filename, byte_im, 'image/jpg')}
# Get poem format
poem_format = get_poem_format()
# Send byte array in API
response = requests.post(api_url, files=files, data={'poem_format': poem_format})
response_data = response.json()
# FOR DEBUGGING: print response to console for debugging
#print(response_data['poem'])
############
# print poem
############
# wrap text to 32 characters per line (max width of receipt printer)
printable_poem = wrap_text(response_data['poem'], 32)
printer.justify('L') # left align poem text
printer.println(printable_poem)
##############
# print footer
##############
printer.justify('C') # center align footer text
printer.println(" . . . . . ")
printer.println("_.` `._.` `._.` `._.` `._.` `._")
printer.println('\n')
printer.println(' This poem was written by AI.')
printer.println()
printer.println('Explore the archives at')
printer.println('poetry.camera')
printer.println('\n\n\n\n')
print('----- DONE PRINTING')
return
##############
# POWER BUTTON
##############
def shutdown():
print('shutdown button held for 2s')
print('shutting down now')
os.system('sudo shutdown -h now')
##################################
# KNOB: GET POEM FORMAT
##################################
def get_poem_format():
# default
# note: if no poem format is passed to API,
# the prompt will default to "2 verses of 4 lines, ABAB rhyme scheme" (knob 1)
poem_format = '8 lines or less, ABAB rhyme scheme'
if knob1.is_pressed:
# default/auto
poem_format = '8 lines or less, ABAB rhyme scheme'
elif knob2.is_pressed:
poem_format = 'haiku'
elif knob3.is_pressed:
poem_format = 'limerick'
elif knob4.is_pressed:
poem_format = 'sonnet'
elif knob5.is_pressed:
poem_format = 'short poem about the people in this scene. what they look like, how they feel, what their stories are. if there are multiple people, what their relationships might be to each other.'
elif knob6.is_pressed:
poem_format = 'short poem about the landscape, background, or location of this scene'
elif knob7.is_pressed:
poem_format = 'short poem about the text described in this scene'
elif knob8.is_pressed:
poem_format = 'short poem in the style of T.S. Eliot'
elif knob9.is_pressed:
poem_format = 'short poem in the style of William Shakespeare'
elif knob10.is_pressed:
poem_format = 'short poem in the style of Emily Dickinson'
# For debugging
print('----- POEM FORMAT: ' + poem_format)
return poem_format
#################################
# For RPi debugging:
# Handle Ctrl+C script termination gracefully
# (Otherwise, it shuts down the entire Pi -- bad)
#################################
def handle_keyboard_interrupt(sig, frame):
print('Ctrl+C received, stopping script')
#weird workaround I found from rpi forum to shut down script without crashing the pi
os.kill(os.getpid(), signal.SIGUSR1)
signal.signal(signal.SIGINT, handle_keyboard_interrupt)
################################
# LISTEN FOR BUTTON PRESS EVENTS
################################
shutter_button.when_pressed = take_photo_and_print_poem
power_button.when_held = shutdown
# knob switch events
signal.pause()