-
Notifications
You must be signed in to change notification settings - Fork 0
/
foto_api.py
executable file
·156 lines (144 loc) · 5.19 KB
/
foto_api.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
#!/usr/bin/env python3
import os
from flask import Flask, request, send_file
from flask_restx import Api, Resource, fields
try:
from picamera2 import Picamera2
from libcamera import Transform
except ImportError:
Picamera2 = None
from PIL import Image
import time
# Initialize Flask app
flask_app = Flask(__name__)
app = Api(
app=flask_app,
version="1.0",
title="Pi Camera Foto API",
description="Takes photos and allows downloading them"
)
# Define namespace
name_space = app.namespace('foto', description='Foto API 2')
# Define data model for the API
model = app.model(
'Foto Properties',
{
'width': fields.Integer(
default=640,
required=False,
description="Width of the photo in pixels",
help="Specify the width in pixels like 640x480 means 640 in width"
),
'height': fields.Integer(
default=480,
required=False,
description="Height of the photo in pixels",
help="Specify the height in pixels like 640x480 means 480 in height"
),
'rotation': fields.Integer(
default=0,
required=False,
description="Photo rotation in degrees",
help="Photo rotation in degrees, should be 0, 90, 180, or 270"
),
'exposure': fields.String(
default='auto',
required=False,
description="Photo exposure mode or exposure time",
help="Photo mode auto, night, sports, etc., or exposure time in microseconds"
),
'iso': fields.Integer(
default=100,
required=False,
description="Photo ISO",
help="ISO Mode 0 ... 800"
),
'filename': fields.String(
default='foto.jpg',
required=False,
description="Filename",
help="Photo filename"
),
}
)
@name_space.route("/")
class MainClass(Resource):
@app.doc(
responses={200: 'OK', 400: 'Invalid Argument', 500: 'Internal Server Error'},
params={'filename': 'Specify the photo filename'}
)
def get(self):
filename = request.args.get('filename', default='foto.jpg', type=str)
try:
file_path = os.path.join('/tmp/', filename)
if os.path.exists(file_path):
response = send_file(file_path, as_attachment=True)
try:
os.remove(file_path)
except FileNotFoundError:
# Log this if needed, but continue
pass
return response
else:
# Return 404 not found
return {"message": "File not found", "statusCode": "404"}, 404
except Exception as e:
# Log the actual exception here if needed for debugging
name_space.abort(
500, e.__doc__, status="Could not retrieve information", statusCode="500"
)
@app.doc(responses={200: 'OK', 400: 'Invalid Argument', 500: 'Mapping Key Error'})
@app.expect(model)
def post(self):
try:
json_input = request.get_json()
# Ensure all expected keys are present
required_fields = ['width', 'height', 'rotation', 'exposure', 'iso', 'filename']
for field in required_fields:
if field not in json_input:
return {"message": f"Missing required field: {field}", "statusCode": "400"}, 400
take_foto(
width=json_input['width'],
height=json_input['height'],
rotation=json_input['rotation'],
exposure=json_input['exposure'],
iso=json_input['iso'],
filename=json_input['filename']
)
return {
"status": "new foto created",
"foto resolution": f"{json_input['width']}x{json_input['height']}",
"foto rotation": json_input['rotation'],
"exposure mode": json_input['exposure'],
"iso": json_input['iso'],
"filename": json_input['filename']
}
except Exception as e:
name_space.abort(
400, e.__doc__, status="Could not save information", statusCode="400"
)
def take_foto(width: int, height: int, rotation: int, exposure: str, iso: int, filename: str):
print(width, height, rotation, exposure, iso, filename)
if Picamera2 is None:
raise RuntimeError("Picamera2 library is not installed.")
picam2 = Picamera2()
camera_config = picam2.create_still_configuration(main={"size": (width, height)}, buffer_count=1)
print(camera_config)
picam2.configure(camera_config)
picam2.start()
file_path = os.path.join('/tmp/', filename)
if os.path.exists(file_path):
os.remove(file_path)
picam2.capture_file(file_path)
picam2.stop()
picam2.close()
with Image.open(file_path) as img:
if rotation != 0:
rotated_img = img.rotate(rotation, expand=True)
rotated_img.save(file_path)
if __name__ == "__main__":
flask_app.run(
host=os.getenv('IP', '0.0.0.0'),
port=8000,
debug=True
)