Example #1
0
    def run(self):
        """
        Méthode principale qui sera exécuter sur un nouveau thread.
        Se charge d'établir une connexion à l'automate et de récupérer la vitesse courante
        toutes les `SLEEP_TIME_MS` millisecondes.
        En cas d'erreur, un pause de `SLEEP_ON_ERROR_MS` millisecondes est prise avant de
        recommencer (depuis le début, création de la connexion incluse).
        """
        self.db = Database(self.db_location)
        try:
            self._connect()
            while True:
                # Récupération de la vitesse
                ts_before = time.time()
                mondon_speed = self._get_speed()

                # Sauvegarde la nouvelle vitesse
                ts = int(round(time.time() * 1000))
                self._save_speed(ts, mondon_speed)

                # Calcule combien de temps on a mis à récupérer et sauvegarder la vitesse
                ts_after = time.time()
                delay = ts_after - ts_before

                # Pause pendant SpeedThread.SLEEP_TIME_MS (moins le temps qu'il a fallu pour
                # récupérer la vitesse et la sauvegarder dans la base de données).
                self.msleep(max(0, SpeedThread.SLEEP_TIME_MS - delay))
        except Exception as e:
            self.ERROR_SIGNAL.emit(str(e))
            logger.log("SPEED_THREAD", "Erreur: {}".format(e))
            self.msleep(SpeedThread.SLEEP_ON_ERROR_MS)
            self.run()
Example #2
0
 def _receive_from_automate(self):
     """
     Attends un message de l'automate
     :return: Retourne le message reçu de l'automate. Retourne un string vide si rien n'a
              été reçu.
     """
     response = self.socket.recv(1024)
     logger.log("SPEED_THREAD", "Reçu de l'automate: {}".format(response))
     return response
Example #3
0
 def _send_to_automate(self, command):
     """
     Envoi une commande à l'automate
     :param command: Commande a envoyer à l'automate
     """
     logger.log(
         "SPEED_THREAD",
         'Envoi de la commande {} ({})'.format(command.description,
                                               command.hex))
     self.socket.sendall(command.binary)
Example #4
0
 def _get_speed(self):
     """
     Simule la récupération d'une nouvelle vitesse en générant une valeur aléatoire.
     Simule une erreur de manière aléatoire 1% du temps.
     :return:
     """
     if randint(0, 100) == 1:
         raise Exception("Simulation d'une erreur!!")
     random_speed = randint(0, 185)
     logger.log(
         "SPEED_THREAD",
         "Génération d'une vitesse aléatoire ({})".format(random_speed))
     return random_speed
Example #5
0
 def _get_speed(self):
     """
     Récupère la vitesse courante de l'automate.
     :return: la vitesse de l'automate.
     """
     self._send_to_automate(GET_SPEED)
     response = self._receive_from_automate()
     if not response:
         raise Exception(
             "Réponse invalide après tentative de récupération de "
             "la vitesse de l'automate: {}".format(response))
     mondon_speed = int.from_bytes(response[-4:], byteorder="big")
     logger.log("SPEED_THREAD",
                "Nouvelle vitesse reçue: {}".format(mondon_speed))
     return mondon_speed
 def insert_speed(self, value, time):
     """
     Insert une nouvelle vitesse dans la base de données
     :param value: Valeur de la vitesse à insérer
     :param time: Temps à lequel la vitesse a été reçu
     """
     try:
         self._run_query("INSERT INTO mondon_speed VALUES (?, ?)",
                         (time, value))
     except sqlite3.IntegrityError as e:
         # IntegrityError veut dire que l'on essaye d'insérer une vitesse avec un timestamp
         # qui existe déjà dans la base de données.
         # Dans ce cas, on considère que cette valeur n'a pas besoin d'être insérée et on
         # ignore l'exception.
         logger.log("DATABASE", "(Ignorée) IntegrityError: {}".format(e))
         pass
    def _run_query(self, query, args):
        """
        Exécute une requête sur la base de données
        :param query: Requête SQL à exécuter
        :param args: Paramètre de la requête à exécuter
        :return: Un array avec le résultat de la requête.
                 Retourne un tableau vide pour les CREATE et INSERT
        """
        logger.log("DATABASE",
                   "Requête: {} - Paramêtres: {}".format(query, args))
        data = None
        attempt = 0

        while attempt < Database.MAX_ATTEMPT_ON_ERROR:
            if attempt > 0:
                sleep(Database.SLEEP_ON_ERROR_MS /
                      1000)  # Pause entre 2 tentatives
                logger.log(
                    "DATABASE",
                    "(Tentative #{}) Requête: {} - Paramêtres: {}".format(
                        attempt + 1, query, args))
            try:
                cursor = self.conn.cursor()
                cursor.execute(query, args)
                self.conn.commit()
                data = cursor.fetchall()
                break
            except sqlite3.OperationalError as e:
                # OperationalError veut généralement dire que la base de données est locked ou
                # de manière générale qu'une erreur s'est produite lors de la lecture du fichier
                # où la base de données est stockée.
                logger.log("DATABASE", "OperationalError: {}".format(e))
                attempt += 1
            except sqlite3.DatabaseError as e:
                if e.__class__.__name__ == "DatabaseError":
                    # DatabaseError veut généralement dire qu'une erreur grave s'est produite.
                    # En générale, cela veut dire que la base de données est corrompue et l'on ne
                    # peut pas faire grand chose. On essaye quand même de s'en sortir en recréant
                    # la connexion à la base de données.
                    logger.log("DATABASE", "DatabaseError: {}".format(e))
                    attempt += 1
                    self._init_db_connection()
                # Si l'exception n'est pas directement une DatabaseError (ex: une sous class de
                # DatabaseError comme IntegrityError), on abandonne directement.
                else:
                    raise e

        # Dans le cas où on a consommé tous les essais possible, on génère une erreur
        if attempt >= Database.MAX_ATTEMPT_ON_ERROR:
            raise Exception(
                "Abandon de la requête {} avec les paramètres {}. Une erreur s'est"
                "produite à chacun des {} essais".format(
                    query, args, Database.MAX_ATTEMPT_ON_ERROR))

        return data
Example #8
0
 def _save_speed(self, ts, speed):
     """
     Gère l'insertion de la nouvelle vitesse dans la base de données et signal le résultat.
     :param speed_value: Nouvelle vitesse
     :param ts: Millitimestamp de quand on a reçu la vitesse
     """
     logger.log(
         "SPEED_THREAD", "Insert vitesse {} au temps {}".format(
             speed, SpeedThread.timestamp_to_date(ts)))
     try:
         self.db.insert_speed(speed, ts)
         self.NEW_SPEED_SIGNAL.emit(speed, ts)
     except Exception as e:
         self.ERROR_SIGNAL.emit(str(e))
         logger.log(
             "SPEED_THREAD",
             "Erreur lors de l'insertion dans la base de données: {}".
             format(e))
Example #9
0
 def _init_socket(self):
     """
     Crée une nouvelle socket (et ferme la socket courante si il y en a une) et connecte la
     à l'automate.
     """
     logger.log("SPEED_THREAD", "Initialization de la socket")
     if self.socket:
         logger.log("SPEED_THREAD",
                    "Socket déjà initialisée, fermeture de la socket")
         self.socket.close()
     logger.log("SPEED_THREAD", "Création d'une socket")
     self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
     logger.log(
         "SPEED_THREAD", "Connexion à {}:{}".format(self.automate_ip,
                                                    self.automate_port))
     self.socket.connect((self.automate_ip, self.automate_port))
 def _init_db_connection(self):
     logger.log(
         "DATABASE", "Connection à la base de données {}".format(
             self.database_location))
     self.conn = sqlite3.connect(self.database_location)
Example #11
0
 def _connect(self):
     """
     Simule la connexion à l'automate. Ne fait rien à part un log.
     """
     logger.log("SPEED_THREAD", "Simulation d'une connexion à l'automate")
Example #12
0
import sys

from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication

from objct.main_window import MainWindow
from objct.speed_thread import SpeedThread, SpeedThreadSimulator

SIMULATOR_ON = True  # Définit si l'on simule la connexion à l'automate
DB_LOCATION = '../mondon.db'
AUTOMATE_IP = '192.168.0.50'
AUTOMATE_PORT = 9600

logger.log(
    "INITIALISATION",
    "Création de la QApplication avec les paramètres: {}".format(sys.argv))
app = QApplication(sys.argv)

logger.log("INITIALISATION", "Définition de l'icone de l'application")
app.setWindowIcon(QIcon('icon/logo_get_speed.ico'))

logger.log("INITIALISATION", "Création de MainWindow")
window = MainWindow()

logger.log("INITIALISATION", "Configuration de MainWindow")
window.setFixedSize(400, 50)
window.setWindowTitle("Get speed")

logger.log("INITIALISATION", "Affichage de MainWindow")
window.show()
Example #13
0
    first_summary = tr.create_summary()
    while True:
        latest_summary = tr.create_summary()
        tr.print_diff(summary1=first_summary, summary2=latest_summary)
        self_use = resource.getrusage(
            resource.RUSAGE_SELF).ru_maxrss / (1000 * 1000)
        print('Memory usage: {} Mb'.format(self_use))
        sleep(10)


Thread(target=memory_usage_thread_func).start()

logger.log_app_start()

logger.log(
    "INITIALISATION",
    "Création de la QApplication avec les paramètres: {}".format(sys.argv))
app = QApplication(sys.argv)

logger.log("INITIALISATION", "Définition de l'icone de l'application")
app.setWindowIcon(QIcon('icon/logo_get_speed.ico'))

logger.log("INITIALISATION", "Initialisation de Database")
db = Database('../../mondon.db')

logger.log("INITIALISATION", "Création de MainWindow")
window = MainWindow(database=db)

logger.log("INITIALISATION", "Configuration de MainWindow")
window.setFixedSize(250, 50)
window.setWindowTitle("Get speed")
 def log_fn(log_text):
     logger.log('DB_STRESS_TEST', '{} | {}'.format(thread_name.ljust(10), log_text))