Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add image capture from a Raspberry Pi camera. #46

Merged
merged 4 commits into from
Jan 9, 2017
Merged

Conversation

JeetShetty
Copy link
Owner

@JeetShetty JeetShetty commented Jan 5, 2017

This change is Reviewable

@coveralls
Copy link

Coverage Status

Coverage increased (+0.5%) to 86.23% when pulling 21870c5 on picamera into 8932bc4 on master.

"""Creates a new camera wrapper instance.

Args:
folder_path: String of the path name of the folder where pictures
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this I don't think we need to say "String of the." Path name implies it's a string.


def capture(self):
"""Captures an image from the camera."""
filename = self._local_clock.now().strftime('%Y-%m-%d-%H')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do the full timestamp to seconds-level granularity so that we can support taking many pictures per hour or minute. Also, since we're using the filename to store the metadata about the time the picture was taken, I think we should include the UTC offset so that we can parse it back later as a timezone-aware datetime.

One thing to be aware of is that : is an illegal character on some filesystems, so we don't want to use that in our filename.

Also I don't think picamera will add the extension for us, so I think we need to append '.jpg'.

@@ -0,0 +1,27 @@
class Camera(object):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd say it's more like a CameraManager or a PhotoSaver because the only thing the caller can do with it is tell it to save a picture to the filesystem.

self._camera = camera

def capture(self):
"""Captures an image from the camera."""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggests "Captures an image from the camera and saves it to the destination folder." Maybe rename the function to something like save_photo to make the purpose a little clearer.

@@ -190,3 +190,23 @@ def _poll_once(self):
if ml_pumped > 0:
self._watering_event_store.store_water_pumped(
self._local_clock.now(), ml_pumped)


class CameraPoller(SensorPollerBase):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this is clever! It hadn't occurred to me that it would just plug into our pollers.

def capture(self):
"""Captures an image from the camera."""
filename = self._local_clock.now().strftime('%Y-%m-%d-%H')
self._camera.capture(self._folder_path + filename, format='jpeg')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We always want to use os.path.join to combine file paths. There's a lot of subtle things that can go wrong if we do it by hand (especially if we want to work well across platforms). A common bug is to call the function and forget the trailing slash like C:\foo\bar instead of C:\foo\bar\ and then it puts the file at C:\foo\bar2016-01-05.jpeg.

@mtlynch
Copy link
Collaborator

mtlynch commented Jan 6, 2017

If you mention issue #44 in the commit description, Github will cross reference the issue here (but we can also do it in PR comments like this).

@@ -0,0 +1,25 @@
import unittest
import datetime
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

datetime should be first

camera.Camera(folder_path, mock_local_clock, mock_camera).capture()
mock_camera.capture.assert_called_once_with(
'C:\\Users\\Jeet\\2016-07-23-10',
format='jpeg')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest using contextlib.closing here. It calls close automatically at the end of the with block, even if there's an exception.

That's what we'll want actual callers to use.

        with contextlib.closing(camera.Camera(folder_path, mock_local_clock,
                                              mock_camera)) as camera_manager:
            camera_manager.capture()

        mock_camera.capture.assert_called_once_with(
            'C:\\Users\\Jeet\\2016-07-23-10',
            format='jpeg')
        mock_camera.close.assert_called()

@coveralls
Copy link

Coverage Status

Coverage increased (+0.5%) to 86.261% when pulling 46adcd3 on picamera into 8932bc4 on master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.5%) to 86.261% when pulling 316d6f1 on picamera into 8932bc4 on master.

Copy link
Collaborator

@mtlynch mtlynch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

folder_path, mock_local_clock, mock_camera)) as manager:
manager.save_photo()
mock_camera.capture.assert_called_once_with(
'C:/Users/Jeet/2016-07-23T10-51-09.928000+00-00.jpg')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be just one test, like we do the mock_camera.close.assert_called() outside the with. I feel like in this case, it's still all logically part of the same single scenario of taking a photo and releasing the camera manager.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.5%) to 86.261% when pulling 690d05a on picamera into 8932bc4 on master.

@JeetShetty JeetShetty merged commit ebc6002 into master Jan 9, 2017
@JeetShetty JeetShetty deleted the picamera branch January 9, 2017 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants