diff --git a/shepherd/plugins/picam.py b/shepherd/plugins/picam.py index 26b1335..50d9794 100644 --- a/shepherd/plugins/picam.py +++ b/shepherd/plugins/picam.py @@ -43,7 +43,7 @@ class PiCamPlugin(shepherd.plugin.Plugin): confdef.add_def('jpeg_quality', shconf.IntDef(default=80, minval=60, maxval=95, optional=True, helptext="JPEG quality to save with. Max of 95, passed directly to Pillow")) - array = confdef.add_def('trigger', shconf.TableArrayDef( + array = confdef.add_def('trigger', shconf.DictListDef( helptext="Array of triggers that will use all cameras")) array.add_def('hour', shconf.StringDef()) array.add_def('minute', shconf.StringDef()) @@ -55,7 +55,7 @@ class PiCamPlugin(shepherd.plugin.Plugin): self.interface = pluginInterface self.plugins = pluginInterface.other_plugins self.hooks = pluginInterface.hooks - + self.root_dir = os.path.expanduser(pluginInterface.coreconfig["root_dir"]) self.id = pluginInterface.coreconfig["id"] @@ -70,7 +70,7 @@ class PiCamPlugin(shepherd.plugin.Plugin): # Seconds to wait for exposure and white balance auto-adjust to stabilise self.stabilise_delay = 3 - if self.config["save_directory"] is "": + if self.config["save_directory"] == "": self.save_directory = os.path.join(self.root_dir, "picamera") else: self.save_directory = self.config["save_directory"] @@ -120,21 +120,20 @@ class PiCamPlugin(shepherd.plugin.Plugin): draw = ImageDraw.Draw(overlay) draw.text((margin_size*2, margin_size), desc_text, - font=thisfont, fill=(255, 255, 255, 255)) + font=thisfont, fill=(255, 255, 255, 255)) datewidth, _ = draw.textsize(time_text, thisfont) draw.text((overlay.width-(margin_size*2)-datewidth, margin_size), time_text, font=thisfont, - fill=(255, 255, 255, 255)) + fill=(255, 255, 255, 255)) # make whole overlay half transparent overlay.putalpha(128) return overlay - def camera_job(self): self.hooks.pre_cam() - #Capture image + # Capture image print("Running camera...") stream = io.BytesIO() with PiCamera() as picam: @@ -146,7 +145,7 @@ class PiCamPlugin(shepherd.plugin.Plugin): stream.seek(0) img = Image.open(stream) - #Process image + # Process image image_time = datetime.now() if self.config["show_overlay"]: diff --git a/shepherd/plugins/uploader.py b/shepherd/plugins/uploader.py index 710d36e..92e50b6 100644 --- a/shepherd/plugins/uploader.py +++ b/shepherd/plugins/uploader.py @@ -151,7 +151,7 @@ class Bucket(): (not item.endswith(".uploading")) and (not item.endswith(".uploaded"))): bucket_files.append(item_path) - #TODO check for .uploaded files and either delete or + # TODO check for .uploaded files and either delete or # if keep_copy, move to self.old_path if bucket_files: @@ -161,7 +161,7 @@ class Bucket(): class UploaderPlugin(shepherd.plugin.Plugin): @staticmethod def define_config(confdef): - dests = confdef.add_def('destination', shconf.TableArrayDef()) + dests = confdef.add_def('destination', shconf.DictListDef()) dests.add_def('name', shconf.StringDef()) dests.add_def('protocol', shconf.StringDef()) dests.add_def('address', shconf.StringDef(optional=True)) @@ -174,7 +174,7 @@ class UploaderPlugin(shepherd.plugin.Plugin): dests.add_def('add_id_to_path', shconf.BoolDef( default=True, optional=True)) - buckets = confdef.add_def('bucket', shconf.TableArrayDef()) + buckets = confdef.add_def('bucket', shconf.DictListDef()) buckets.add_def('name', shconf.StringDef()) buckets.add_def('open_link_on_new', shconf.BoolDef()) buckets.add_def('opportunistic', shconf.BoolDef( @@ -215,7 +215,7 @@ class UploaderPlugin(shepherd.plugin.Plugin): def move_to_bucket(self, filepath, bucket_name): # use intermediary step with ".writing" on the filename - # in case the source isn't in the same filesystem and so the + # in case the source isn't in the same filesystem and so the # move operation might not be atomic. Once it's there, the rename # _is_ atomic dest_path = os.path.join(self.buckets[bucket_name].path, diff --git a/shepherd/plugins/usbcam.py b/shepherd/plugins/usbcam.py index 3adfad1..717ac85 100644 --- a/shepherd/plugins/usbcam.py +++ b/shepherd/plugins/usbcam.py @@ -29,11 +29,15 @@ CameraPort = namedtuple( 'CameraPort', ['usbPath', 'devicePath']) # Short wrapper to allow use in a ``with`` context + + class VideoCaptureCtx(): def __init__(self, *args, **kwargs): self.capture_dev = cv2.VideoCapture(*args, **kwargs) + def __enter__(self): return self.capture_dev + def __exit__(self, *args): self.capture_dev.release() @@ -116,13 +120,13 @@ class USBCamPlugin(shepherd.plugin.Plugin): confdef.add_def('stabilise_delay', shconf.IntDef(default=5, minval=1, maxval=30, optional=True, helptext="Number of seconds to wait after starting each camera for exposure and white balance to settle")) - array = confdef.add_def('trigger', shconf.TableArrayDef( + array = confdef.add_def('trigger', shconf.DictListDef( helptext="Array of triggers that will use all cameras")) array.add_def('hour', shconf.StringDef()) array.add_def('minute', shconf.StringDef()) array.add_def('second', shconf.StringDef(default="0", optional=True)) - camarray = confdef.add_def('camera', shconf.TableArrayDef( + camarray = confdef.add_def('camera', shconf.DictListDef( helptext="List of cameras to try and connect to. Multiple ports may be listed, and any not connected will be skipped on each trigger.")) camarray.add_def('name', shconf.StringDef(default="", optional=False, helptext="Name of camera, appended to filename and added to overlay")) @@ -150,7 +154,7 @@ class USBCamPlugin(shepherd.plugin.Plugin): self.gstlock = threading.Lock() - if self.config["save_directory"] is "": + if self.config["save_directory"] == "": self.save_directory = os.path.join(self.root_dir, "usbcamera") else: self.save_directory = self.config["save_directory"] @@ -237,7 +241,7 @@ class USBCamPlugin(shepherd.plugin.Plugin): if self.config["append_id"]: image_filename = image_filename + " " + self.id - if camera_name is not "": + if camera_name != "": image_filename = image_filename+" "+camera_name image_filename = image_filename + ".jpg" image_filename = os.path.join(self.save_directory, image_filename) @@ -252,48 +256,46 @@ class USBCamPlugin(shepherd.plugin.Plugin): with self.gstlock: - #gst_str = ('v4l2src device='+device_path+' ! ' + # gst_str = ('v4l2src device='+device_path+' ! ' # 'videoconvert ! appsink drop=true max-buffers=1 sync=false') - #vidcap = cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER) + # vidcap = cv2.VideoCapture(gst_str, cv2.CAP_GSTREAMER) fmts = get_capture_formats(device_path) - + with VideoCaptureCtx(device_path, cv2.CAP_V4L2) as vidcap: if "MJPG" in fmts: size = get_largest_resolution(fmts["MJPG"]) set_camera_format_opencv(vidcap, "MJPG", size[0], size[1]) - # stream only starts after first grab - + print("Starting cam") read_flag, frame = vidcap.read() delay_start = time.time() while (time.time() - delay_start) < self.config["stabilise_delay"]: vidcap.grab() - #time.sleep(self.config["stabilise_delay"]) + # time.sleep(self.config["stabilise_delay"]) # clear old buffer - #print("Flushing capture") - #vidcap.grab() + # print("Flushing capture") + # vidcap.grab() print("Reading") read_flag, frame = vidcap.read() - #print("Changing to YUYV") - #if "YUYV" in fmts: + # print("Changing to YUYV") + # if "YUYV" in fmts: # size = get_largest_resolution(fmts["YUYV"]) # set_camera_format_opencv(vidcap, "YUYV", size[0], size[1]) - #print("Reading again") - #read_flag, frame2 = vidcap.read() - + # print("Reading again") + # read_flag, frame2 = vidcap.read() if read_flag: self._process_image(frame, camera_name) - #self._process_image(frame2, camera_name+"(2)") + # self._process_image(frame2, camera_name+"(2)") else: print("Could not read camera "+camera_name + " on USB port "+device_path) - def run_cameras(self, name_suffix = ""): + def run_cameras(self, name_suffix=""): connected_cams = OrderedDict(get_connected_cameras()) for defined_name, defined_usb_path in self.defined_cams.items(): @@ -317,7 +319,7 @@ class USBCamPlugin(shepherd.plugin.Plugin): def camera_job(self): self.hooks.pre_cam() - self.run_cameras() + self.run_cameras() self.hooks.post_cam()