Beispiel #1
0
class Lock():
	def __init__(self):
		# initialize board
		self.greLED = 19
		self.redLED = 13
		self.yelLED = 6
		self.buttonPin = 4
		self.updatePin = 17
		self.servoPin = 12
		GPIO.setmode(GPIO.BCM)
		GPIO.setup(self.redLED, GPIO.OUT)
		GPIO.setup(self.yelLED, GPIO.OUT)
		GPIO.setup(self.greLED, GPIO.OUT)
		GPIO.setup(self.buttonPin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
		GPIO.setup(self.updatePin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
		GPIO.setup(self.servoPin, GPIO.OUT)
		self.servo = GPIO.PWM(self.servoPin, 50) # 50 Hz
		self.servo.start(5)		# door closed
		self._lightUp(1,1,1)

		# model initializer
		print("Intialize model... ", end="")
		t0 = perf_counter()
		self.model = Predictor()
		print("finished! elapsed time: {} secs".format(perf_counter()-t0))

		# initialize camera
		self.cam = PiCamera()
		self.img_path = '/home/pi/Desktop/test.jpg'

		# initialze mongo
		self.client = MongoClient(MONGO_URI)
		self.db = self.client['lock']
		this_lock = self.db.locks.find_one()
		self.lock_id = this_lock['_id']
		self.lock_code = this_lock['lockCode']

		# sound files
		self.welcome_sounds = dict()
		self.updateAllUsersSounds()
		self.access_granted_sound = AudioSegment.from_mp3('./sounds/access_granted.mp3')
		self.access_denied_sound = AudioSegment.from_mp3('./sounds/access_denied.mp3')
		self.update_detected_sound = AudioSegment.from_mp3('./sounds/update_detected.mp3')
		self.update_complete_sound = AudioSegment.from_mp3('./sounds/update_complete.mp3')

		# ready to use
		print("lock is ready to be used")
		self._lightUp(0,0,1)	# standby light

	# take a picture and validate
	def validate(self):
		print("Taking picture...")
		self.cam.start_preview()
		self.cam.capture(self.img_path)
		self.cam.stop_preview()

		result = self.model.predictFromPath(self.img_path) # username or None

		# open the lock or deny access
		if result is not None:
			print(" Welcome {}!".format(result))
			self._grantAccess(result)
		else:
			self._denyAccess()

		# send history to mongo
		buffer = None
		with open(self.img_path, "rb") as image:
			buffer = image.read()
		new_history = {
			'img': {'data': buffer},
			'accepted': result != None,
			'timestamp': str(datetime.datetime.now()),
			'username': result if result != None else 'unknown'
		}

		print("sending image to db")
		self.db.locks.update_one({'_id': self.lock_id}, {'$push': {'history': new_history}})
		self.db.update_status.update_one({'lockCode': self.lock_code}, {'$set': {'history_status': True}})
		print("done sending image to db")



	# return True if the button is pressed, otherwise false
	def isPressed(self):
		return GPIO.input(self.buttonPin) == GPIO.HIGH

	def imagesUpdateRequested(self):
		# print("pin status:", GPIO.input(self.updatePin))
		return GPIO.input(self.updatePin) == GPIO.HIGH

	# check if an update is pending, if yes, update
	def checkUpdate(self):
		update_needed = self.db['update_status'].find_one()['user_status']
		if update_needed:
			self.updateImages()

	def updateImages(self):

		self._lightUp(1,1,1)	# update in progress
		play(self.update_detected_sound)

		# initialize mongo
		lock_mongo = self.db.locks.find_one()

		images = lock_mongo['images']
		users_need_update = []
		images_on_db = set()

		for image in images:
			username = image['username']
			filename = image['filename']
			img_data = image['img']['data']
			print("processing image {}".format(filename))

			user_folder_path = './{}/{}'.format(USERS_FOLDER_PATH, username)
			if not os.path.isdir(user_folder_path):
				os.mkdir(user_folder_path)
				self.updateUserSound(username)	# add welcome sound

			img_path = '{}/{}.png'.format(user_folder_path, filename)
			images_on_db.add(img_path)

			if os.path.isfile(img_path):
				print("img {} already exists".format(filename))
				continue
			users_need_update.append(username)
			self.model.addImagePath(username, img_path)
			with open(img_path, 'wb') as file:
				file.write(img_data)

		# check if any image was deleted on db, if yes, delete them on the pi too
		img_paths_to_delte = []
		for img_path in self.model.imagesPaths.keys():
			if img_path not in images_on_db:
				img_paths_to_delte.append(img_path)
		for img_path in img_paths_to_delte:
			print("deleting", img_path)
			os.remove(img_path)
			username = self.model.imagesPaths[img_path]
			print("adding {} to list of users need update".format(username))
			users_need_update.append(username)
			del self.model.imagesPaths[img_path]

		print("updating users encoding")
		for username in users_need_update:
			print("update encoding of {}".format(username))
			self.model.updateUserEncoding(username)
		print("done updating encodings")
		self.db['update_status'].update_one({'lockCode': self.lock_code}, {'$set': {'user_status': False}})
		play(self.update_complete_sound)
		self._lightUp(0,0,1)	# standby light

	def updateAllUsersSounds(self):
		for username in os.listdir(USERS_FOLDER_PATH):
			sound_path = './sounds/welcome_{}.mp3'.format(username)
			if os.path.isfile(sound_path):
				self.welcome_sounds[username] = AudioSegment.from_mp3(sound_path)
				continue
			self.updateUserSound(username)

	def updateUserSound(self, username):
		s = "welcome {}".format(username)
		sound_path = './sounds/welcome_{}.mp3'.format(username)
		tts = gTTS(text=s, lang="en", tld="com")
		tts.save(sound_path)
		self.welcome_sounds[username] = AudioSegment.from_mp3(sound_path)

	def updateUserEncoding(self, user):
		self.model.updateUserEncoding(user)

	def _grantAccess(self, username):
		self._lightUp(0,1,0)	# green light
		print("---Access Granted---")

		# open door
		self.servo.ChangeDutyCycle(10)

		# sounds
		play(self.access_granted_sound)
		play(self.welcome_sounds[username])

		# close door
		time.sleep(1)
		self.servo.ChangeDutyCycle(5)
		time.sleep(1)

		self._lightUp(0,0,1) # back to standby light

	def _denyAccess(self):
		self._lightUp(1,0,0)	# red light
		print("---Access Denied---")
		play(self.access_denied_sound)
		time.sleep(2)
		self._lightUp(0,0,1) # back to standby light

	def _lightUp(self,r,g,y):
		GPIO.output(self.redLED, r)
		GPIO.output(self.yelLED, y)
		GPIO.output(self.greLED, g)