Skip to content

Commit

Permalink
Merge pull request #23 from Postcard/v0.3.2
Browse files Browse the repository at this point in the history
V0.3.2
  • Loading branch information
benoitguigal committed May 20, 2015
2 parents d74d49c + 158444f commit bfcedc5
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 130 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ RUN wget --no-check-certificate https://github.com/aeberhardo/phantomjs-linux-ar
bunzip2 *.bz2 && \
tar xf *.tar

RUN echo 'disable cache'
RUN wget --no-check-certificate https://github.com/benoitguigal/python-epson-printer/archive/v1.7.1.zip && \
unzip v1.7.1.zip && \
rm v1.7.1.zip && \
Expand All @@ -60,7 +59,8 @@ RUN pip install gphoto2==1.1.0 \
Flask==0.10.1 \
supervisor==3.1.3 \
Django==1.8 \
gunicorn==19.3.0
gunicorn==19.3.0 \
python-dateutil==2.4.2

ENV LANG C.UTF-8
ENV C_FORCE_ROOT true
Expand Down
52 changes: 29 additions & 23 deletions figureraspbian/devices/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,53 +49,59 @@ def capture(self, installation):

# Capture image
error, filepath = gp.gp_camera_capture(self.camera, gp.GP_CAPTURE_IMAGE, self.context)
folder = filepath.folder
name = filepath.name

if settings.FLASH_ON:
self.light.flash_off()

# Get date
error, info = gp.gp_camera_file_get_info(
self.camera,
folder,
name,
self.context)
date = datetime.fromtimestamp(info.file.mtime)
timezone = pytz.timezone(settings.TIMEZONE)
timezone.localize(date)

# Get snapshot file
error, camera_file = gp.gp_camera_file_get(
self.camera,
filepath.folder,
filepath.name,
folder,
name,
gp.GP_FILE_TYPE_NORMAL,
self.context)

error, file_data = gp.gp_file_get_data_and_size(camera_file)

# Crop and rotate snapshot
snapshot = Image.open(io.BytesIO(file_data))
if settings.CAMERA_TYPE == 'NIKON':
w, h = snapshot.size
left = (w - h) / 2
top = 0
right = w - left
bottom = h
snapshot = snapshot.crop((left, top, right, bottom))
elif settings.CAMERA_TYPE == 'CANON':
w, h = snapshot.size
left = (w - h) / 2
top = 0
right = w - left
bottom = h
snapshot = snapshot.crop((left, top, right, bottom))
if settings.CAMERA_TYPE == 'CANON':
snapshot = snapshot.rotate(90)
w, h = snapshot.size
left = 0
top = (h - w) / 2
right = w
bottom = h - top
snapshot = snapshot.crop((left, top, right, bottom))
else:
raise Exception("Unknown camera type")

# resize in place using the fastest algorithm, ie NEAREST
small = snapshot.resize((512, 512))

# Create file path on the RaspberryPi
now = datetime.now().strftime('%Y%m%d%H%M%S')
datetime.now(pytz.timezone(settings.TIMEZONE))
basename = "{installation}_{now}.jpg".format(installation=installation, now=now)
basename = "{installation}_{date}.jpg".format(installation=installation, date=date.strftime('%Y%m%d%H%M%S'))
path = os.path.join(settings.MEDIA_ROOT, 'snapshots', basename)

small.save(path)

return path, snapshot
return path, snapshot, date

finally:
del camera_file, file_data
if 'camera_file' in locals():
del camera_file
if 'file_data' in locals():
del file_data
self.camera.exit(self.context)


Expand Down
4 changes: 0 additions & 4 deletions figureraspbian/phantomjs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
from . import settings


class PhantomJsException(Exception):
pass


def get_screenshot():
args = [settings.PHANTOMJS_PATH, './figureraspbian/ticket.js']
data = subprocess.check_output(args)
Expand Down
32 changes: 21 additions & 11 deletions figureraspbian/processus.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

from os.path import basename, join
import time
import shutil
import logging
logging.basicConfig(level='INFO')
logger = logging.getLogger(__name__)
import codecs
from PIL import Image

from .ticketrenderer import TicketRenderer
from . import devices, settings
from . import devices, settings, ticketrenderer
from .db import Database, managed
import phantomjs

Expand All @@ -32,7 +32,7 @@ def run():

# Take a snapshot
start = time.time()
snapshot_path, snapshot = devices.CAMERA.capture(installation.id)
snapshot_path, snapshot, date = devices.CAMERA.capture(installation.id)
end = time.time()
logger.info('Snapshot capture successfully executed in %s seconds', end - start)
# Start blinking
Expand All @@ -41,16 +41,24 @@ def run():
# Render ticket
start = time.time()
code = db.get_code()
renderer = TicketRenderer(ticket_template['html'],
ticket_template['text_variables'],
ticket_template['image_variables'],
ticket_template['images'])
html, dt, code, random_text_selections, random_image_selections = \
renderer.render(snapshot_path, code)
random_text_selections = [ticketrenderer.random_selection(variable) for
variable in
ticket_template['text_variables']]
random_image_selections = [ticketrenderer.random_selection(variable) for
variable in
ticket_template['image_variables']]
rendered_html = ticketrenderer.render(
ticket_template['html'],
snapshot_path,
code,
date,
ticket_template['images'],
random_text_selections,
random_image_selections)
ticket_html_path = join(settings.STATIC_ROOT, 'ticket.html')

with codecs.open(ticket_html_path, 'w', 'utf-8') as ticket_html:
ticket_html.write(html)
ticket_html.write(rendered_html)

# get ticket as base64 stream
ticket_data = phantomjs.get_screenshot()
Expand Down Expand Up @@ -78,13 +86,15 @@ def run():
# Get good quality image in order to upload it
snapshot.thumbnail((1024, 1024), Image.ANTIALIAS)
snapshot.save(snapshot_path)
if settings.BACKUP_ON:
shutil.copy2(snapshot_path, "/mnt/%s" % basename(snapshot_path))

# add task upload ticket task to the queue
ticket = {
'installation': installation.id,
'snapshot': snapshot_path,
'ticket': ticket_path,
'dt': dt,
'dt': date,
'code': code,
'random_text_selections': random_text_selections,
'random_image_selections': random_image_selections
Expand Down
4 changes: 4 additions & 0 deletions figureraspbian/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def get_env_setting(setting, default=None):
flash_on = get_env_setting('FLASH_ON', '0')
FLASH_ON = True if flash_on == '1' else False

# Backup
backup_on = get_env_setting('BACKUP_ON', '0')
BACKUP_ON = True if backup_on == '1' else False


def log_config():
logger.info('RESIN_DEVICE_UUID: %s' % RESIN_DEVICE_UUID)
Expand Down
74 changes: 37 additions & 37 deletions figureraspbian/tests.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
# -*- coding: utf8 -*-

import unittest
import re
import os
from datetime import datetime
from dateutil import parser
import pytz
from .ticketrenderer import TicketRenderer
from .utils import url2name
from .db import Database, managed
from . import api, settings, processus, devices
from mock import MagicMock, Mock, call
from . import api, settings, processus, devices, ticketrenderer
from mock import MagicMock, Mock, call, patch
import urllib2
from ZEO import ClientStorage
from ZODB import DB
Expand All @@ -22,63 +21,64 @@

class TestTicketRenderer(unittest.TestCase):

def setUp(self):
html = '{{snapshot}} {{code}} {{datetime | datetimeformat}} {{textvariable_1}} {{imagevariable_2}} {{image_1}}'
self.chiefs = ['Titi', 'Vicky', 'Benni']
self.chiefs = [{'id': '1', 'text': 'Titi'}, {'id': '2', 'text': 'Vicky'}, {'id': '3', 'text': 'Benni'}]
text_variables = [{'id': '1', 'items': self.chiefs}]
self.paths = [{'id': '1', 'image': '/path/to/variable/image1'}, {'id': '2', 'image': '/path/to/variable/image2'}]
image_variables = [{'id': '2', 'items': self.paths}, {'id': '3', 'items': []}]
images = [{'id': '1', 'image': 'path/to/image'}]
self.ticket_renderer = TicketRenderer(html, text_variables, image_variables, images)

def test_random_selection(self):
"""
random selection should randomly select variable items
"""
random_text_selections, random_image_selections = self.ticket_renderer.random_selection()
self.assertTrue(len(random_text_selections), 1)
self.assertEqual(random_text_selections[0][0], '1')
self.assertTrue(random_text_selections[0][1] in self.chiefs)
self.assertTrue(len(random_image_selections), 1)
self.assertEqual(random_image_selections[0][0], '2')
self.assertTrue(random_image_selections[0][1] in self.paths)
items = ['item1', 'item2', 'item3']
variable = {'id': '1', 'items': ['item1', 'item2', 'item3']}
id, item = ticketrenderer.random_selection(variable)
self.assertEqual(id, '1')
self.assertIn(item, items)

def test_random_selection_empty_variable(self):
"""
random selection should not throw if no items in variable
"""
variable = {'id': '1', 'items': []}
_, item = ticketrenderer.random_selection(variable)
self.assertIsNone(item)

def test_render(self):
"""
TicketRenderer should render a ticket
"""
html = '{{snapshot}} {{code}} {{datetime | datetimeformat}} {{textvariable_1}} {{imagevariable_2}} {{image_1}}'
code = '5KIJ7'
rendered_html, _, _, _, _ = self.ticket_renderer.render('/path/to/snapshot', code)
print rendered_html
date = parser.parse("Tue Jun 22 07:46:22 EST 2010")
images = [{'id': '1', 'image': 'path/to/image'}]
random_text_selections = [('1', {'id': '2', 'text': 'Titi'}), ('2', None)]
random_image_slections = [('2', {'id': 1, 'image': '/path/to/image'})]
rendered_html = ticketrenderer.render(
html,
'/path/to/snapshot',
code,
date,
images,
random_text_selections,
random_image_slections)
expected = 'http://localhost:8080/media/snapshots/snapshot 5KIJ7 2010-06-22 Titi ' \
'http://localhost:8080/media/images/image http://localhost:8080/media/images/image'
self.assertIn(expected, rendered_html)

def test_set_date_format(self):
"""
Ticket renderer should handle datetimeformat filter
"""
html = '{{datetime | datetimeformat("%Y")}}'
self.ticket_renderer.html = html
rendered_html, _, _, _, _ = self.ticket_renderer.render('/path/to/snapshot', '00000')
self.assertRegexpMatches(rendered_html, re.compile("\d{4}"))
date = parser.parse("Tue Jun 22 07:46:22 EST 2010")
rendered_html = ticketrenderer.render(html, '/path/to/snapshot', '00000', date, [], [], [])
self.assertIn("2010", rendered_html)

def test_encode_non_unicode_character(self):
"""
Ticket renderer should encode non unicode character
"""
html = u"Du texte avec un accent ici: é"
self.ticket_renderer.html = html
rendered_html, _, _, _, _ = self.ticket_renderer.render('/path/to/snapshot', '00000')
date = parser.parse("Tue Jun 22 07:46:22 EST 2010")
rendered_html = ticketrenderer.render(html, '/path/to/snapshot', '00000', date, [], [], [])
self.assertTrue(u'Du texte avec un accent ici: é' in rendered_html)

def test_render_multiple_times(self):
"""
Ticket renderer should render tickets multiples times with different codes
"""
rendered1 = self.ticket_renderer.render('/path/to/snapshot', '00000')
rendered2 = self.ticket_renderer.render('/path/to/snapshot', '00001')
self.assertIn('00000', rendered1)
self.assertIn('00001', rendered2)


class TestUtilityFunction(unittest.TestCase):

Expand Down
Loading

0 comments on commit bfcedc5

Please sign in to comment.