...
 
Commits (3)
......@@ -28,6 +28,7 @@ def getMainWin():
ON_RASP = os.uname()[1] == 'raspberrypi'
IMG_PATH = getContent('img')
SIDE = None
if __name__=='__main__':
__package__ = 'Babyfut'
......@@ -35,10 +36,12 @@ if __name__=='__main__':
from Babyfut.modules import GameModule
from Babyfut.core.player import Side
from Babyfut.core.input import GPIOThread
from Babyfut.core.downloader import Downloader
from Babyfut.core.database import Database
from Babyfut.core.replay import Replay as ReplayThread
try:
SIDE = Side.Left
#logging.basicConfig(filename='babyfoot.log', level=logging.DEBUG)
logging.basicConfig(level=logging.DEBUG)
......@@ -53,12 +56,17 @@ if __name__=='__main__':
threadReplay.start()
myapp.dispatchMessage({'replayThread': threadReplay}, toType=GameModule)
threadGPIO = GPIOThread(myapp)
threadGPIO = GPIOThread()
threadGPIO.rfidReceived.connect(myapp.rfidHandler)
threadGPIO.start()
threadDownloader = Downloader.instance()
threadDownloader.start()
myapp.show()
app.exec_()
threadDownloader.stop()
threadGPIO.stop()
if ReplayThread.isCamAvailable():
......@@ -66,6 +74,7 @@ if __name__=='__main__':
threadReplay.join()
threadGPIO.join()
threadDownloader.join()
finally:
GPIOThread.clean()
......
......@@ -6,6 +6,8 @@
import sqlite3
from Babyfut.babyfut import getContent
class DatabaseError(Exception):
pass
......@@ -14,7 +16,6 @@ class Database():
def __init__(self):
if not Database.__db:
from Babyfut.babyfut import getContent
db_path = getContent('babyfut.sqlite')
self._connection = sqlite3.connect(db_path)
......@@ -23,7 +24,6 @@ class Database():
'''
Singleton
'''
if not Database.__db:
Database.__db = Database()
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Apr 18 18:34:40 2018
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import os
import logging
import urllib.request
from time import sleep
from threading import Thread
from PyQt5.QtCore import QObject, pyqtSignal, pyqtSlot
class Downloader(Thread, QObject):
'''
Helper for downloading images using queues
'''
N_ATTEMPS = 5
__instance = None
finished = pyqtSignal(str)
def __init__(self):
Thread.__init__(self)
QObject.__init__(self)
# Mandatory header if we want servers to accept the request
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
urllib.request.install_opener(opener)
self._close = False
self._request_stack = []
@staticmethod
def instance():
if Downloader.__instance==None:
Downloader.__instance = Downloader()
return Downloader.__instance
def request(self, url_in, uri_out, nAttemps=None):
if nAttemps==None:
nAttemps = Downloader.N_ATTEMPS
print('Adding "{}". {} before it'.format(url_in, len(self._request_stack)))
self._request_stack.append((url_in, uri_out, nAttemps))
def run(self):
while not self._close:
if len(self._request_stack)>0:
url_in, uri_out, nAttemps = self._request_stack.pop()
nAttemps -= 1
urllib.request.urlretrieve(url_in, uri_out)#FIXME , timeout=1000)
if os.path.exists(uri_out):
logging.debug('Downloaded "{}". {} still queued'.format(url_in, len(self._request_stack)))
self.finished.emit(uri_out)
elif nAttemps!=0:
logging.info('Failed to download "{}". {} attemps remaining'.format(url_in, nAttemps))
self.request(url_in, uri_out, nAttemps)
sleep(1)
def stop(self):
self._close = True
......@@ -5,8 +5,12 @@
"""
import logging
import pyautogui # PyPi library
import time
from threading import Thread
import pyautogui # PyPi library
from pirc522 import RFID # PyPi library
from PyQt5.QtCore import QObject, pyqtSignal
from Babyfut.babyfut import ON_RASP
from Babyfut.core.player import Side
......@@ -14,7 +18,7 @@ from Babyfut.core.player import Side
if ON_RASP:
import RPi.GPIO as GPIO
class GPIOThread(Thread):
class GPIOThread(Thread, QObject):
_keyButtonBindings = {
26: 'up',
22: 'left',
......@@ -23,11 +27,15 @@ class GPIOThread(Thread):
17: 'return',
18: 'escape'
}
rfidReceived = pyqtSignal(str)
def __init__(self, dispatcher):
def __init__(self):
Thread.__init__(self)
self.dispatcher = dispatcher
QObject.__init__(self)
self.rf_reader = RFID(pin_rst=25, pin_ce=8, pin_irq=24, pin_mode=GPIO.BCM)
self.continueRunning = True
self.lastRFIDReception = 0
if ON_RASP:
GPIO.setwarnings(False)
......@@ -42,9 +50,25 @@ class GPIOThread(Thread):
if ON_RASP:
try:
while self.continueRunning:
pass
self.rf_reader.wait_for_tag()
(error, tag_type) = self.rf_reader.request()
if not error:
self.handleRFID()
finally:
GPIOThread.clean()
self.clean()
def handleRFID(self):
(error, id) = self.rf_reader.anticoll()
if not error:
# Prevent RFID "spam" (one second removal delay)
now = time.time()
if self.lastRFIDReception!=0 and abs(self.lastRFIDReception-now)>1:
self.lastRFIDReception = 0
receivedRFID = ':'.join([str(x) for x in id])
self.rfidReceived.emit(receivedRFID)
logging.debug('Received RFID: {}'.format(receivedRFID))
else:
self.lastRFIDReception = now
def handleButtonPress(self, button_pin):
if button_pin not in GPIOThread._keyButtonBindings.keys():
......@@ -56,6 +80,12 @@ class GPIOThread(Thread):
def stop(self):
self.continueRunning = False
# Falsely trigger the rfid reader to stop it waiting
self.rf_reader.irq.set()
def clean(self):
GPIOThread.clean()
self.rf_reader.cleanup()
@staticmethod
def clean():
......
......@@ -9,10 +9,11 @@ Created on Wed Apr 18 18:34:40 2018
import logging
from enum import Enum
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtWidgets import QDialog
from PyQt5.QtCore import Qt, QCoreApplication, QObject, pyqtSlot, QEvent
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QDialog, QApplication
from Babyfut.babyfut import getMainWin
from Babyfut.babyfut import getMainWin, IMG_PATH
from Babyfut.core.database import Database, DatabaseError
from Babyfut.ui.consent_dialog_ui import Ui_Dialog as ConsentDialogUI
......@@ -55,7 +56,7 @@ class ConsentDialog(QDialog):
else:
self.reject()
class Player():
class Player(QObject):
__query_infos = 'SELECT id, fname, lname, pic FROM Players WHERE rfid==?'
__query_time_goals_games = 'SELECT SUM(Matchs.duration) AS timePlayed, SUM(Teams.nGoals) AS goalsScored, COUNT(*) AS gamesPlayed FROM Teams INNER JOIN Matchs ON (Teams.id==Matchs.winningTeam OR Teams.id==Matchs.losingTeam) WHERE (Teams.player1==? OR player2==?)'
__query_victories = 'SELECT COUNT(*) AS victories FROM Players INNER JOIN Teams ON (Players.id==Teams.player1 OR Players.id==Teams.player2) INNER JOIN Matchs ON (Teams.id==Matchs.winningTeam) WHERE Players.id==?'
......@@ -111,11 +112,20 @@ class Player():
if self.pic_path.startswith('http'):
# Download from the internet
container_widget.setStyleSheet('border-image: url({});'.format(Player._placeholder_pic_path))
# TODO DOWNLOAD
self.pic_container.setStyleSheet('border-image: url({});'.format(Player._placeholder_pic_path))
Downloader.instance().request(self.pic_path, os.path.join(IMG_PATH, '{}.jpg'.format(self.id)))
Downloader.instance().finished.connect(self._downloader_callback)
else:
# Already downloaded and stored locally
container_widget.setStyleSheet('border-image: url({});'.format(self.pic_path))
self.pic_container.setStyleSheet('border-image: url({});'.format(self.pic_path))
self._forceWidgetUpdate()
QApplication.processEvents()
@pyqtSlot(str)
def _downloader_callback(self, path):
self.pic_path = path
Downloader.instance().finished.disconnect(self._downloader_callback)
self.displayImg(self.pic_container)
def save(self):
'''
......
......@@ -3,7 +3,7 @@
"""
@author: Antoine Lima, Leo Reynaert, Domitille Jehenne
"""
import subprocess
from threading import Thread, Event
from Babyfut.babyfut import getContent, ON_RASP
......@@ -17,12 +17,15 @@ class Replay(Thread):
Thread.__init__(self)
self.replayPath = getContent('Replay {}.mp4'.format(side.name))
self.shutdown = False
if ON_RASP:
self.camera_detected = Replay.detectCam()
self.start_flag = Event()
self.stop_flag = Event()
self.stopped_flag = Event()
if ON_RASP:
if self.isCamAvailable():
self.cam = picamera.PiCamera()
self.cam.resolution = Settings['picam.resolution']
self.cam.framerate = Settings['picam.fps']
......@@ -31,11 +34,11 @@ class Replay(Thread):
self.stream = picamera.PiCameraCircularIO(self.cam, seconds=Settings['replay.duration'])
def start_recording(self):
if ON_RASP:
if self.isCamAvailable():
self.start_flag.set()
def stop_recording(self):
if ON_RASP:
if self.isCamAvailable():
self.stop_flag.set()
self.stopped_flag.wait()
......@@ -77,5 +80,11 @@ class Replay(Thread):
return getContent('Replay Left.mp4')
@staticmethod
def isCamAvailable():
return ON_RASP # and other checks (ToDo)
def detectCam():
camdet = subprocess.check_output(["vcgencmd","get_camera"])
return int(chr(camdet[-2]))
@staticmethod
def isCamAvailable(self=None):
detected = self.camera_detected if self!=None else Replay.detectCam()
return ON_RASP and detected
......@@ -59,12 +59,12 @@ case "$1" in
bash ./devtools.sh "clean"
bash ./devtools.sh "all"
;;
"exec")
"run"|"exec")
cd ..
python -m Babyfut.babyfut
;;
*)
echo "Unknown command \"$1\". See content of script for available commands."
echo "Unknown command \"$1\". See script for available commands."
;;
esac
......