all_on and all_off
This commit is contained in:
parent
62b6bb2417
commit
727ab37b0b
|
|
@ -1,6 +1,6 @@
|
|||
from flask import Flask, send_from_directory, session
|
||||
import os
|
||||
from . import db, config, routes, utils
|
||||
from . import db, config, routes, utils, leds
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
|
|
@ -25,7 +25,7 @@ def inject():
|
|||
conn = db.get()
|
||||
return {
|
||||
'calibration': utils.get_calibration(conn),
|
||||
'leds': config.GPIO_LEDS.leds,
|
||||
'leds': leds.get().leds,
|
||||
'CalibrationState': db.CalibrationState,
|
||||
}
|
||||
|
||||
|
|
|
|||
45
camera.py
45
camera.py
|
|
@ -1,42 +1,47 @@
|
|||
import gphoto2 as gp
|
||||
import shutil
|
||||
from . import leds
|
||||
from . import leds, config
|
||||
|
||||
|
||||
class Camera:
|
||||
def capture(self, output_path: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
class RealCamera(Camera):
|
||||
def __init__(self):
|
||||
self.inner = gp.Camera()
|
||||
|
||||
def __enter__(self):
|
||||
self.inner.init()
|
||||
return self
|
||||
|
||||
def __exit__(self):
|
||||
def __exit__(self, *args):
|
||||
self.inner.exit()
|
||||
|
||||
def capture(self, output_path: str) -> bool:
|
||||
try:
|
||||
with self:
|
||||
file_path = self.inner.capture(gp.GP_CAPTURE_IMAGE)
|
||||
preview = self.inner.file_get(file_path.folder, file_path.name[:-3] + '.JPG', gp.GP_FILE_TYPE_NORMAL)
|
||||
raw = self.inner.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_RAW)
|
||||
file_path = self.inner.capture(gp.GP_CAPTURE_IMAGE)
|
||||
preview = self.inner.file_get(file_path.folder, file_path.name[:-3] + '.JPG', gp.GP_FILE_TYPE_NORMAL)
|
||||
raw = self.inner.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_RAW)
|
||||
|
||||
preview.sve(output_path + '.jpg')
|
||||
raw.save(output_path + '.cr2')
|
||||
return True
|
||||
preview.sve(output_path + '.jpg')
|
||||
raw.save(output_path + '.cr2')
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print('An error occured when capturing photo', e)
|
||||
return False
|
||||
|
||||
|
||||
class DummyCamera:
|
||||
class DummyCamera(Camera):
|
||||
def __init__(self, leds: leds.DummyLeds):
|
||||
self.leds = leds
|
||||
|
||||
def __enter__(self):
|
||||
pass
|
||||
return self
|
||||
|
||||
def __exit__(self):
|
||||
def __exit__(self, *args):
|
||||
pass
|
||||
|
||||
def capture(self, output_path: str) -> bool:
|
||||
|
|
@ -50,9 +55,17 @@ class DummyCamera:
|
|||
else:
|
||||
all_on = True
|
||||
|
||||
if found:
|
||||
if all_on:
|
||||
shutil.copyfile('data-keep/small/all_on.jpg', output_path + '.jpg')
|
||||
elif found is not None:
|
||||
shutil.copyfile('data-keep/small/' + str(found) + '.jpg', output_path + '.jpg')
|
||||
elif all_on:
|
||||
shutil.copyfile('data-keep/small/LED17.jpg', output_path + '.jpg')
|
||||
else:
|
||||
shutil.copyfile('data-keep/small/LED17.jpg', output_path + '.jpg')
|
||||
print('ALL_OFF')
|
||||
shutil.copyfile('data-keep/small/all_off.jpg', output_path + '.jpg')
|
||||
|
||||
|
||||
camera = DummyCamera(leds.get()) if config.CAMERA == "dummy" else RealCamera()
|
||||
|
||||
|
||||
def get():
|
||||
return camera
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from os.path import join
|
||||
from . import camera, leds
|
||||
|
||||
DATA_DIR = 'data'
|
||||
BACKUPS_DIR = 'data-backups'
|
||||
|
|
@ -10,5 +9,4 @@ DATABASE_PATH = join(DATA_DIR, 'db.sqlite')
|
|||
AUTO_USE_LAST_CALIBRATION = True
|
||||
GPIO_CHIP = 'gpiochip0'
|
||||
LEDS_UUIDS = [17, 18, 22, 23, 24, 27]
|
||||
GPIO_LEDS = leds.GpioLeds(LEDS_UUIDS)
|
||||
CAMERA = camera.Camera()
|
||||
CAMERA = 'real'
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from os.path import join
|
||||
from . import camera, leds
|
||||
|
||||
DATA_DIR = 'data'
|
||||
BACKUPS_DIR = 'data-backups'
|
||||
|
|
@ -10,5 +9,4 @@ DATABASE_PATH = join(DATA_DIR, 'db.sqlite')
|
|||
AUTO_USE_LAST_CALIBRATION = False
|
||||
GPIO_CHIP = None
|
||||
LEDS_UUIDS = [17, 18, 22, 23, 24, 27]
|
||||
GPIO_LEDS = leds.DummyLeds(LEDS_UUIDS)
|
||||
CAMERA = camera.DummyCamera(GPIO_LEDS)
|
||||
CAMERA = 'dummy'
|
||||
|
|
|
|||
29
leds.py
29
leds.py
|
|
@ -1,5 +1,21 @@
|
|||
import gpiod
|
||||
|
||||
from . import config
|
||||
|
||||
|
||||
class Leds:
|
||||
def __enter__(self):
|
||||
pass
|
||||
|
||||
def __exit__(self, *args):
|
||||
pass
|
||||
|
||||
def on(self):
|
||||
pass
|
||||
|
||||
def off(self):
|
||||
pass
|
||||
|
||||
|
||||
class GpioLed:
|
||||
def __init__(self, gpio_pin: int):
|
||||
|
|
@ -26,7 +42,7 @@ class GpioLed:
|
|||
return f'LED{self.gpio_pin:02}'
|
||||
|
||||
|
||||
class GpioLeds:
|
||||
class GpioLeds(Leds):
|
||||
def __init__(self, chip: str, gpio_pins: list[int]):
|
||||
self.chip = gpiod.Chip(chip)
|
||||
self.leds = []
|
||||
|
|
@ -36,6 +52,7 @@ class GpioLeds:
|
|||
def __enter__(self):
|
||||
for led in self.leds:
|
||||
led.enter(self.chip)
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
for led in self.leds:
|
||||
|
|
@ -71,7 +88,7 @@ class DummyLed:
|
|||
return f'LED{self.gpio_pin:02}'
|
||||
|
||||
|
||||
class DummyLeds:
|
||||
class DummyLeds(Leds):
|
||||
def __init__(self, gpio_pins: list[int]):
|
||||
self.leds = []
|
||||
for pin in gpio_pins:
|
||||
|
|
@ -80,6 +97,7 @@ class DummyLeds:
|
|||
def __enter__(self):
|
||||
for led in self.leds:
|
||||
led.enter()
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
for led in self.leds:
|
||||
|
|
@ -92,3 +110,10 @@ class DummyLeds:
|
|||
def on(self):
|
||||
for led in self.leds:
|
||||
led.on()
|
||||
|
||||
|
||||
_leds = GpioLeds(config.GPIO_CHIP, config.LEDS_UUIDS) if config.GPIO_CHIP is not None else DummyLeds(config.LEDS_UUIDS)
|
||||
|
||||
|
||||
def get() -> Leds:
|
||||
return _leds
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ def scan_existing(id: int):
|
|||
conn = db.get()
|
||||
calibrated = session.get('calibration_id', None) is not None
|
||||
acquisition = db.Acquisition.get_from_id(id, conn)
|
||||
object = acquisition.object(conn)
|
||||
object = acquisition.object(conn) if acquisition is not None else None
|
||||
return render_template('scan.html', object=object, acquisition=acquisition, calibrated=calibrated)
|
||||
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ def run(object_id: int):
|
|||
|
||||
def generate():
|
||||
yield str(acquisition.id)
|
||||
length = len(config.LEDS_UUIDS)
|
||||
length = len(config.LEDS_UUIDS) + 2 # with all_on and all_off
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.OBJECT_DIR, str(object.id), str(acquisition.id)))):
|
||||
yield f"{led_uuid},{(index+1)/length}\n"
|
||||
|
||||
|
|
@ -74,7 +74,7 @@ def rescan(acquisition_id: int):
|
|||
object = acquisition.object(conn)
|
||||
|
||||
def generate():
|
||||
length = len(config.LEDS_UUIDS)
|
||||
length = len(config.LEDS_UUIDS) + 2 # with all_on and all_off
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.OBJECT_DIR, str(object.id), str(acquisition.id)))):
|
||||
yield f"{led_uuid},{(index+1)/length}\n"
|
||||
|
||||
|
|
@ -87,7 +87,7 @@ def validate(acquisition_id: int):
|
|||
acquisition = db.Acquisition.get_from_id(acquisition_id, conn)
|
||||
|
||||
if acquisition is None:
|
||||
raise f"Aucune acquisition d'id {acquisition_id}"
|
||||
raise Exception(f"Aucune acquisition d'id {acquisition_id}")
|
||||
|
||||
object = acquisition.object(conn)
|
||||
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ def scan():
|
|||
|
||||
def generate():
|
||||
length = len(config.LEDS_UUIDS)
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.CALIBRATION_DIR, calibration_id))):
|
||||
for index, led_uuid in enumerate(scanner.scan(join(config.CALIBRATION_DIR, calibration_id), False)):
|
||||
yield f"{led_uuid},{(index+1)/length}\n"
|
||||
|
||||
with conn:
|
||||
|
|
|
|||
61
scanner.py
61
scanner.py
|
|
@ -1,42 +1,51 @@
|
|||
import os
|
||||
from os.path import join
|
||||
import time
|
||||
from . import config
|
||||
from . import leds, camera
|
||||
|
||||
# Delay between to captures
|
||||
DELAY = 0.5
|
||||
|
||||
|
||||
def scan(output_dir: str):
|
||||
def delay_capture(cam, output_path):
|
||||
# Measure the time it takes to capture
|
||||
start = time.time()
|
||||
output = cam.capture(output_path)
|
||||
delta = time.time() - start
|
||||
|
||||
# Wait for at least one second between each capture
|
||||
if delta < DELAY:
|
||||
time.sleep(DELAY - delta)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def scan(output_dir: str, on_and_off: bool = True):
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
with config.GPIO_LEDS:
|
||||
for count, led in enumerate(config.GPIO_LEDS.leds):
|
||||
print(f'Turn on {led}')
|
||||
img = join(output_dir, f'{led}')
|
||||
with leds.get() as gpio_leds:
|
||||
for count, led in enumerate(gpio_leds.leds):
|
||||
with camera.get() as cam:
|
||||
print(f'Turn on {led}')
|
||||
img = join(output_dir, f'{led}')
|
||||
|
||||
# Measure the time it takes to capture
|
||||
start = time.time()
|
||||
led.on()
|
||||
delay_capture(cam, img)
|
||||
led.off()
|
||||
|
||||
led.on()
|
||||
config.CAMERA.capture(img)
|
||||
led.off()
|
||||
print(f'Turn off {led}')
|
||||
yield str(led)
|
||||
|
||||
delta = time.time() - start
|
||||
|
||||
# Wait for at least one second between each capture
|
||||
if delta < DELAY:
|
||||
time.sleep(DELAY - delta)
|
||||
|
||||
print(f'Turn off {led}')
|
||||
if count == len(config.LEDS_UUIDS) - 1:
|
||||
# capture with all leds ON OFF
|
||||
config.GPIO_LEDS.on()
|
||||
# capture with all leds ON OFF
|
||||
if on_and_off:
|
||||
with camera.get() as cam:
|
||||
gpio_leds.on()
|
||||
img = join(output_dir, 'all_on')
|
||||
config.CAMERA.capture(img)
|
||||
delay_capture(cam, img)
|
||||
yield 'all_on'
|
||||
|
||||
config.GPIO_LEDS.off()
|
||||
with camera.get() as cam:
|
||||
gpio_leds.off()
|
||||
img = join(output_dir, 'all_off')
|
||||
config.CAMERA.capture(img)
|
||||
|
||||
yield led
|
||||
delay_capture(cam, img)
|
||||
yield 'all_off'
|
||||
|
|
|
|||
|
|
@ -102,6 +102,22 @@
|
|||
cell.appendChild(img);
|
||||
grid.appendChild(cell);
|
||||
{% endfor %}
|
||||
|
||||
cell = document.createElement('div');
|
||||
cell.classList.add('cell');
|
||||
img = document.createElement('img');
|
||||
img.classList.add('is-loading');
|
||||
img.src = '/data/objects/{{ object.id }}/' + acquisitionId + '/all_on.jpg?v=0';
|
||||
cell.appendChild(img);
|
||||
grid.appendChild(cell);
|
||||
|
||||
cell = document.createElement('div');
|
||||
cell.classList.add('cell');
|
||||
img = document.createElement('img');
|
||||
img.classList.add('is-loading');
|
||||
img.src = '/data/objects/{{ object.id }}/' + acquisitionId + '/all_off.jpg?v=0';
|
||||
cell.appendChild(img);
|
||||
grid.appendChild(cell);
|
||||
}
|
||||
|
||||
scanButton.addEventListener('click', async () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue