예제 #1
0
	def jobRun(self):


		### List all jpg files in the current local sub-folder
		self._locdir = os.path.join(self._config['image_dir'], self._imageFIFO.crtSubDir)
		self._image_names = os.path.join(self._locdir, self._imageFIFO.crtSubDir + '-*' + self._imageFIFO.camID + '.jpg')
		self.imagelist = sorted(glob.glob(self._image_names))
		if len(self.imagelist) > 0:
			logging.debug("imagelist: %s .. %s" % (self.imagelist[0], self.imagelist[-1]))
		else:
			logging.debug("imagelist: empty. No %s found!" % self._image_names)

		### Run directory/file management only if no errors were detected when
		### updating to remote directory
		if not self._eventDbErr.is_set():
			# Process the new list only if it is changed and has at least max length
			if ( not (self._imagelist_ref == self.imagelist) ) and \
				len(self.imagelist) > self._config['list_size']:

				# Remove all the local images, which are
				# not in the camera buffer and are in the uploaded images buffer
				try:
					self._imageFIFO.acquireSemaphore()
					self._imageUpldFIFO.acquireSemaphore()

					for img in self.imagelist:
						if not img in self._imageFIFO and \
							img in self._imageUpldFIFO:
							logging.info("Remove image: %s" % img)
							self._rmimg = subprocess.Popen("rm " + img, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)
							self._diroutput, self._direrrors = self._rmimg.communicate()


				except OSError as e:
					raise rpiBaseClassError("%s::: jobRun(): File %s could not be deleted!\n%s" % (self.name, img, e), ERRLEV2)

				except:
					raise rpiBaseClassError("%s::: jobRun(): Unhandled Exception:\n%s" % (self.name, str(sys.exc_info())), ERRCRIT)

				finally:
					self._imageFIFO.releaseSemaphore()
					self._imageUpldFIFO.releaseSemaphore()

			#raise rpiBaseClassError("%s::: jobRun(): Test crash!" % self.name, 4)

			# Update status
			self.statusUpdate = (self.name, len(self.imagelist))

			# Update image list in the current local sub-folder
			self._imagelist_ref = sorted(glob.glob(self._image_names))
			if len(self._imagelist_ref) > 0:
				logging.debug("imagelist_ref: %s .. %s" % (self._imagelist_ref[0], self.imagelist[-1]))
			else:
				logging.debug("imagelist_ref: empty. No %s found!" % self._image_names)


		else:
			logging.info("eventDbErr is set!")
예제 #2
0
	def _mkdirImage(self, path):
		"""
		Create a new remote directory.

		Examples:
		_mkdirImage('/dropbox_dir_test')
		"""
		try:
			self._dbx.files_create_folder('/' + os.path.normpath(path))

			logging.debug("%s::: Remote output folder /%s created." % (self.name, path))

		except ApiError as e:
			noerr = False
			# dropbox.files.CreateFolderError
			if e.error.is_path():
				# dropbox.files.WriteError
				we = e.error.get_path()
				if we.is_conflict():
					# dropbox.files.WriteConflictError
					wce = we.get_conflict()
					# union tag is 'folder'
					if wce.is_folder():
						logging.info("%s::: Remote output folder /%s already exist!" % (self.name, path))
						noerr = True

			if not noerr:
				raise rpiBaseClassError("_mkdirImage(): Remote output folder /%s was not created! %s" % (path, e.error), ERRCRIT)
			else:
				pass
예제 #3
0
	def endDayOAM(self):
		"""
		End-of-Day Operation and Maintenance sequence.
		"""

		self._lsImage(self.upldir)
		logging.info("%s::: %d images in the remote folder %s" % (self.name, len(self.imageDbList), self.upldir))

		# Lock the uplaod buffer
		self.imageUpldFIFO.acquireSemaphore()

		try:
			upldimg=[]
			for img in self.imageUpldFIFO:
				upldimg.append(img)

			with open(self.logfile,'w') as logf:
				json.dump(upldimg, logf)

			del upldimg

			logging.info("%s::: Local log file %s updated." % (self.name, self.logfile))

		except IOError:
			raise rpiBaseClassError("endDayOAM(): Local log file %s was not found." % self.logfile,  ERRCRIT)

		finally:
			# Release the upload buffer
			self.imageUpldFIFO.releaseSemaphore()
예제 #4
0
	def _mvImage(self, from_path, to_path):
		"""
		Move/rename a remote file or directory.

		Examples:
		_mvImage('./path1/dropbox-move-test.jpg', '/path2/dropbox-move-test.jpg')
		"""
		try:
			self._dbx.files_move( '/' + os.path.normpath(from_path), '/' +  os.path.normpath(to_path) )

			logging.debug("%s::: _mvImage(): Moved file from %s to %s" % (self.name, from_path, to_path))

		except ApiError as e:
			raise rpiBaseClassError("_mvImage(): Image %s could not be moved to %s! %s" % (from_path, to_path, e.error), ERRLEV2)
예제 #5
0
	def _putImage(self, from_path, to_path, overwrite=False):
		"""
		Copy local file to remote file.
		Stores the uploaded files names in self.imageUpldFIFO.

		Examples:
		_putImage('./path/test.jpg', '/path/dropbox-upload-test.jpg')
		"""
		try:
			mode = (WriteMode.overwrite if overwrite else WriteMode.add)

			with open(from_path, "rb") as from_file:
				self._dbx.files_upload( from_file, '/' + os.path.normpath(to_path), mode)

			if not overwrite:
				self.imageUpldFIFO.append(from_path)

			logging.debug("%s::: _putImage(): Uploaded file from %s to remote %s" % (self.name, from_path, to_path))

		except IOError:
			raise rpiBaseClassError("_putImage(): Local img file %s could not be opened." %  from_path, ERRCRIT)

		except ApiError as e:
			raise rpiBaseClassError("_putImage(): %s" % e.error, ERRLEV2)
예제 #6
0
	def _lsImage(self,from_path):
		"""
		List the image/video files in the remote directory.
		Stores the found file names in self.imageDbList.
		"""
		try:
			if self._imageDbCursor is None:
				self.ls_ref = self._dbx.files_list_folder('/' + os.path.normpath(from_path), recursive=False, include_media_info=True )
			else:
				new_ls = self._dbx.files_list_folder_continue(self._imageDbCursor)
				if new_ls.entries == []:
					logging.debug("%s::: _lsImage():: No changes on the server." % self.name)
				else:
					self.ls_ref = new_ls

			# Select only images and only the ones for the current imgid (camid)
			foundImg = False
			for f in self.ls_ref.entries:
				if 'media_info' in f._all_field_names_ and \
					f.media_info is not None:
					if self.imgid in f.path_lower:
						img = '.%s' % f.path_lower
						foundImg = True
						if not img in self.imageDbList:
							self.imageDbList.append(img)


			if not foundImg:
				self.imageDbList = []

			### Store the hash of the folder
			self._imageDbCursor = self.ls_ref.cursor

			if len(self.imageDbList) > 0:
				logging.debug("%s::: _lsImage():: imageDbList[0..%d]: %s .. %s" % (self.name, len(self.imageDbList)-1, self.imageDbList[0], self.imageDbList[-1]) )
			else:
				logging.debug("%s::: _lsImage():: imageDbList[]: empty" % self.name)

		except ApiError as e:
			raise rpiBaseClassError("_lsImage(): %s" % e.error, ERRLEV2)
예제 #7
0
파일: rpicam.py 프로젝트: istvanzk/rpicampy
	def initClass(self):
		""""
		(re)Initialize the class.
		"""

		### Host/cam ID
		self._camera = None
		self.camid = 'CAM1'
		if subprocess.check_output(["hostname", ""], shell=True).strip().decode('utf-8').find('pi2') > 0:
			self.camid = 'CAM2'

		### Init the FIFO buffer
		self.imageFIFO.camID = self.camid
		self.imageFIFO.clear()
		self.crtlenFIFO = 0

		### Init the "dark" time flag and reference image brightness
		# (used only when RPICAM or RASPISTILL= True)
		self.bDarkExp = False
		self.imgbr = 128

		### Init GPIO ports
		self.IRport = 19 # use GPIO19
		if USEGPIO:
			GPIO.cleanup(self.IRport)
			GPIO.setmode(GPIO.BCM)
			GPIO.setup(self.IRport, GPIO.OUT, initial=0)

		### Init the font
		self._TXTfont = ImageFont.truetype("/usr/share/fonts/truetype/freefont/FreeSans.ttf", 16)

		### Create output folder
		try:
			os.mkdir(self._config['image_dir'])
			self.imgSubDir = time.strftime('%d%m%y', time.localtime())
			logging.info("%s::: Local output folder %s created." % (self.name, self._config['image_dir']))
		except OSError as e:
			if e.errno == EEXIST:
				logging.info("%s::: Local output folder %s already exist!" % (self.name, self._config['image_dir']))
				pass
			else:
				raise rpiBaseClassError("%s::: initClass(): Local output folder %s could not be created" % (self.name, self._config['image_dir']) , ERRCRIT)

		### Fill in the fifo buffer with images found in the output directory
		### Only the image files with the current date are listed!
		#imagelist_ref = sorted(glob.glob(self._config['image_dir'] + '/' + time.strftime('%d%m%y', time.localtime()) + '-*.jpg'))
		#self.imageFIFO.acquireSemaphore()
		#for img in imagelist_ref:
		#	if not img in self.imageFIFO:
		#		self.imageFIFO.append(img)
		#self.imageFIFO.releaseSemaphore()

		# Ephem parameters
		# The ephem.localtime() function converts a PyEphem date into a Python datetime object 
		# expressed in your local time zone.
		# A negative value of horizon can be used when an observer is high off of the ground.
		self._sun = ephem.Sun()
		self._loc = ephem.Observer()
		self._loc.lat = self._config['dark_loc'][0]
		self._loc.lon = self._config['dark_loc'][1]
		self._loc.pressure = 0
		self._loc.horizon = '-2:30'
예제 #8
0
파일: rpicam.py 프로젝트: istvanzk/rpicampy
	def jobRun(self):

		### Create the daily output sub-folder
		### Set the full image file path
		#self._config['image_subdir'] = time.strftime('%d%m%y', time.localtime())
		self.imageFIFO.crtSubDir = time.strftime('%d%m%y', time.localtime())
		self._locdir = os.path.join(self._config['image_dir'], self.imageFIFO.crtSubDir)
		try:
			os.mkdir(self._locdir)
			logging.info("%s::: Local daily output folder %s created." % (self.name, self._locdir))

		except OSError as e:
			if e.errno == EEXIST:
				logging.debug("%s::: Local daily output folder %s already exist!" % (self.name, self._locdir))
				pass
			else:
				raise rpiBaseClassError("%s::: jobRun(): Local daily output folder %s could not be created" % (self.name, self._locdir) , ERRCRIT)

		finally:
			self.image_name = self.imageFIFO.crtSubDir + '-' + time.strftime('%H%M%S', time.localtime()) + '-' + self.camid + '.jpg'
			self.image_path = os.path.join(self._locdir, self.image_name)


		### Take a new snapshot and save the image locally
		try:
			# Lock the buffer
			self.imageFIFO.acquireSemaphore()

			if FAKESNAP:
				logging.debug('Faking snapshot: ' + self.image_name)
				self._grab_cam = subprocess.Popen("touch " + self.image_path, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

				# Check return/errors
				self._camoutput, self._camerrors = self._grab_cam.communicate()

			elif RASPISTILL:
				# Use raspistill -n -vf -hf -awb auto -q 95
				self._grab_cam = subprocess.Popen("raspistill -n -vf -hf -q 95 -co 30 -w 640 -h 480 -o " + self.image_path, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

				# Check return/errors
				#self.grab_cam.wait()
				self._camoutput, self._camerrors = self._grab_cam.communicate()

			elif RPICAM:
				# Init the camera
				#with picamera.PiCamera() as self._camera:
				self._camera = picamera.PiCamera()
				self._camera.resolution = (1024, 768)
				self._camera.exif_tags['IFD0.Copyright'] = 'Copyright (c) 2016 Istvan Z. Kovacs'
				#self._camera.hflip = True
				#self._camera.vflip = True
				self._camera.rotation = 0
				if self.camid == 'CAM1':
					self._camera.rotation = 90
				elif self.camid == 'CAM2':
					self._camera.rotation = 180


				# Set camera exposure according to the 'dark' time threshold
				self._setCamExp()

				# Create the in-memory stream
				stream = io.BytesIO()

				# Camera warm-up time and capture
				self._camera.capture(stream, format='jpeg')

				# Read stream to a PIL image
				stream.seek(0)
				image = Image.open(stream)

				# When in 'dark' time
				# Calculate brightness and adjust shutter speed
				sN = ': '
				if self.bDarkExp:
					sN = 'n' + sN

					if self.camid == 'CAM1':

						# Calculate brightness
						#self._grayscaleAverage(image)
						self._averagePerceived(image)

						# Recapture image with new shutter speed if needed
						if self.imgbr < 118 or \
							self.imgbr > 138:

							# Release the buffer (this capture could take a few seconds)
							self.imageFIFO.releaseSemaphore()

							# Shutter speed (micro seconds)
							ss = self._camera.shutter_speed
							logging.debug('Before: Br=%d, Ss=%dus' % (self.imgbr, ss))

							# Re-capture the picture
							time.sleep(3)
							self._camera.shutter_speed = int(ss*(2 - float(self.imgbr)/128))
							self._camera.capture(stream, format='jpeg')
							stream.seek(0)
							image = Image.open(stream)

							# Re-calculate brightness
							self._averagePerceived(image)
							logging.debug('After: Br=%d, Ss=%dus' % (self.imgbr, self._camera.shutter_speed))

							# Lock the buffer
							self.imageFIFO.acquireSemaphore()

					#elif self.camid == 'CAM2':
						# Do nothing ?

					#else:
						# Do nothing ?


				# Add overlay text to the final image
				draw = ImageDraw.Draw(image,'RGBA')
				draw.rectangle([0,image.size[1]-20,image.size[0],image.size[1]], fill=(150,200,150,100))
				draw.text((2,image.size[1]-18), self.camid + sN + time.strftime('%b %d %Y, %H:%M', time.localtime()), fill=(0,0,0,0), font=self._TXTfont)
				#n_width, n_height = TXTfont.getsize('#XX')
				#draw.text((image.size[0]-n_width-2,image.size[1]-18), '#XX', fill=(0,0,0,0), font=self._TXTfont)
				del draw

				# Save image and close the stream
				image.save( self.image_path, format='jpeg', quality=95 )
				#image.close()

				# Close BytesIO stream
				stream.close()

				# Set output indicators
				self._camoutput = self.image_path
				self._camerrors = ''

			else:
				# Use fswebcam -d /dev/video0 -s brightness=50% -s gain=32
				self._grab_cam = subprocess.Popen("fswebcam -d /dev/video0 -q -r 640x480 --jpeg=95 " + self.image_path, stderr=subprocess.PIPE, stdout=subprocess.PIPE, shell=True)

				### Check return/errors
				self._camoutput, self._camerrors = self._grab_cam.communicate()


			logging.info('Snapshot: ' + self.image_name)

			### Add image to deque (FIFO)
			self.imageFIFO.append(self.image_path)
			self.crtlenFIFO = len(self.imageFIFO)

			if self.crtlenFIFO > 0:
				logging.debug("imageFIFO[0..%d]: %s .. %s" % (self.crtlenFIFO-1, self.imageFIFO[0], self.imageFIFO[-1]))
			else:
				logging.debug("imageFIFO[]: empty")

			### Update status
			self.statusUpdate = (self.name, self.crtlenFIFO)

			### Close the picamera
			if RPICAM:
				self._camera.close()

		except OSError as e:
			raise rpiBaseClassError("%s::: jobRun(): Snapshot %s could not be created!\n%s" % (self.name, self.image_path, e), ERRLEV2)

		finally:
			# Release the buffer
			self.imageFIFO.releaseSemaphore()
예제 #9
0
	def jobRun(self):

		try:
			# Lock the buffer
			self._imageFIFO.acquireSemaphore()

			# Get the current images in the FIFO
			# Refresh the last remote image when available
			if len(self._imageFIFO):

				# Update remote cam image with the current (last) image
				if not (self._imageFIFO[-1] == self.crt_image_snap):
					self._putImage(self._imageFIFO[-1], self._config['image_snap'], True)
					self.crt_image_snap = self._imageFIFO[-1]
					self.numImgUpdDb += 1
					logging.info("Updated remote %s with %s" % (self._config['image_snap'], self._imageFIFO[-1]) )


				# Lock the upload buffer
				self.imageUpldFIFO.acquireSemaphore()

				# Check if a new upload sub-folder has to be used
				if not (self.imageUpldFIFO.crtSubDir == self._imageFIFO.crtSubDir):
					self.imageUpldFIFO.crtSubDir = self._imageFIFO.crtSubDir
					self.upldir = os.path.normpath(os.path.join(self._config['image_dir'], self.imageUpldFIFO.crtSubDir))
					self._mkdirImage(self.upldir)

				# Upload only images in the FIFO which have not been uploaded yet
				for img in self._imageFIFO:
					if not img in self.imageUpldFIFO:
						self._putImage(img, os.path.join(self.upldir, os.path.basename(img)))
						logging.info("Uploaded %s" % img )

				# Release the upload buffer
				self.imageUpldFIFO.releaseSemaphore()

				# Update status
				self.statusUpdate = (self.name, self.numImgUpdDb)

			else:
				# Update status
				self.statusUpdate = (self.name, ERRNONE)

				logging.info('Nothing to upload')


		# Handle exceptions, mostly HTTP/SSL related!
		except exceptions.Timeout as e:
			# Catching this error will catch both ReadTimeout and ConnectTimeout.
			raise rpiBaseClassError("%s::: jobRun(): Connect/ReadTimeoutError:\n%s" % (self.name, str(e)), ERRLEV2)

		except exceptions.ConnectionError as e:
			# A Connection error occurred.
			raise rpiBaseClassError("%s::: jobRun(): ConnectionError:\n%s" % (self.name, str(e)), ERRLEV2)

		except exceptions.HTTPError as e:
			# An HTTP error occurred.
			raise rpiBaseClassError("%s::: jobRun(): HTTPError:\n%s" % (self.name, str(e)), ERRLEV2)

		except exceptions.RequestException as e:
			# There was an ambiguous exception that occurred while handling your request.
			raise rpiBaseClassError("%s::: jobRun(): RequestException:\n%s" % (self.name, str(e)), ERRLEV2)

# 			except BadStatusLine as e:
# 				self.eventErr_set('run()')
# 				logging.debug("BadStatusLine:\n%s" % str(e))
# 				pass

		except rpiBaseClassError as e:
			if e.errval == ERRCRIT:
				self.endDayOAM()
			raise rpiBaseClassError("%s::: jobRun(): %s" % (self.name, e.errmsg), e.errval)

		except RuntimeError as e:
			self.endDayOAM()
			raise rpiBaseClassError("%s::: jobRun(): RuntimeError:\n%s" % (self.name, str(e)), ERRCRIT)

		except:
			self.endDayOAM()
			raise rpiBaseClassError("%s::: jobRun(): Unhandled Exception:\n%s" % (self.name, str(sys.exc_info())), ERRCRIT)

		finally:
			# Release the buffer
			self._imageFIFO.releaseSemaphore()
예제 #10
0
	def initClass(self):
		""""
		(re)Initialize the class.
		"""

		#self.imageDbHash = None
		self._imageDbCursor = None
		self.imageDbList = []
		self.numImgUpdDb = 0

		self.crt_image_snap = None
		self.imgid = self._imageFIFO.camID + '.jpg'
		self.upldir = os.path.normpath(os.path.join(self._config['image_dir'], self.imageUpldFIFO.crtSubDir))
		self.logfile = './upldlog.json'

		### When there are already images listed in the upload log file, then
		# make sure we don't upload them to the remote folder again
		# Else, create the file with an empty list; to be updated in endDayOAM()
		try:
			self.imageUpldFIFO.acquireSemaphore()
			self.imageUpldFIFO.clear()

			if os.path.isfile(self.logfile):
				with open(self.logfile,'r') as logf:
					upldimg = json.load(logf)

				for img in upldimg:
					self.imageUpldFIFO.append(img)

				del upldimg

				logging.info("%s::: Local log file %s found and loaded." % (self.name, self.logfile))
			else:
				with open(self.logfile,'w') as logf:
					json.dump([], logf)
					logging.info("%s::: Local log file %s initialized." % (self.name, self.logfile))

		except IOError:
			raise rpiBaseClassError("%s::: initClass(): Local log file %s was not found or could not be created." % (self.name, self.logfile), ERRCRIT)

		finally:
			# Release the upload buffer
			self.imageUpldFIFO.releaseSemaphore()

		### Init Dropbox API client
		self._token_file = self._config['token_file']
		self._dbx = None
		self.dbinfo = None
		try:
			with open(self._token_file, 'r') as token:
				self._dbx = Dropbox(token.read())

			info = self._dbx.users_get_current_account()
			# info._all_field_names_ =
			# {'account_id', 'is_paired', 'locale', 'email', 'name', 'team', 'country', 'account_type', 'referral_link'}
			self.dbinfo ={'email': info.email, 'referral_link': info.referral_link}

			logging.info("%s::: Loaded access token from ''%s''" % (self.name, self._token_file) )

			### Create remote root folder (relative to app root) if it does not exist yet
			self._mkdirImage(os.path.normpath(self._config['image_dir']))

		except rpiBaseClassError as e:
			if e.errval == ERRCRIT:
				self.endDayOAM()
			raise rpiBaseClassError("initClass(): %s" % e.errmsg, e.errval)

		except IOError:
			self.endDayOAM()
			raise rpiBaseClassError("initClass(): Token file ''%s'' could not be read." % (self.name, self._token_file), ERRCRIT)

		except AuthError as e:
			self.endDayOAM()
			raise rpiBaseClassError("initClass(): AuthError:\n%s" % e.error, ERRCRIT)

		except DropboxException as e:
			self.endDayOAM()
			raise rpiBaseClassError("initClass(): DropboxException:\n%s" %  str(e), ERRCRIT)

		except InternalServerError as e:
			self.endDayOAM()
			raise rpiBaseClassError("initClass(): InternalServerError:\n%s" % str(e.status_code),  ERRCRIT)