2021-07-05 14:17:40 +02:00
|
|
|
import random
|
2021-06-24 17:22:02 +02:00
|
|
|
import time
|
|
|
|
|
2021-07-05 14:17:40 +02:00
|
|
|
import numpy as np
|
|
|
|
from coapthon import defines
|
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
class SupervisorError(Exception):
|
|
|
|
def __init__(self, *args: object) -> None:
|
|
|
|
super().__init__(*args)
|
|
|
|
|
|
|
|
|
|
|
|
class NoRttError(SupervisorError):
|
|
|
|
def __init__(self, *args: object) -> None:
|
|
|
|
super().__init__(*args)
|
|
|
|
|
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
class SuperviseurLocalPlaceHolder():
|
2021-06-24 17:22:02 +02:00
|
|
|
"""Class de base pour le superviseur
|
|
|
|
"""
|
2021-07-13 14:53:16 +02:00
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
N_MESURE = 0
|
2021-07-01 14:42:48 +02:00
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
def __init__(self, client_CoAP) -> None:
|
2021-07-05 14:17:40 +02:00
|
|
|
client_CoAP.superviseur = self
|
2021-06-24 17:22:02 +02:00
|
|
|
self.client = client_CoAP
|
2021-07-01 14:42:48 +02:00
|
|
|
self._RTTs = []
|
|
|
|
self._taux_retransmition = 0
|
2021-07-05 14:17:40 +02:00
|
|
|
self._RTO = defines.ACK_TIMEOUT
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-13 14:53:16 +02:00
|
|
|
def reset_rto(self):
|
|
|
|
self._RTO = defines.ACK_TIMEOUT
|
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
def envoie_message(self, message) -> None:
|
|
|
|
self.envoie_token(message.token)
|
|
|
|
|
|
|
|
def reception_message(self, message) -> None:
|
|
|
|
self.reception_token(message.token)
|
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
def envoie_token(self, token) -> None:
|
|
|
|
pass
|
|
|
|
|
|
|
|
def reception_token(self, tokken) -> None:
|
|
|
|
pass
|
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
def failed_request(self):
|
|
|
|
pass
|
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
@property
|
|
|
|
def RTTs(self):
|
|
|
|
return self._RTTs
|
|
|
|
|
|
|
|
@property
|
2021-07-05 14:17:40 +02:00
|
|
|
def taux_retransmission(self):
|
2021-07-01 14:42:48 +02:00
|
|
|
return self._taux_retransmition
|
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
@property
|
|
|
|
def min_RTT(self):
|
|
|
|
"""Valeur minimum du RTT"""
|
2021-07-09 11:46:42 +02:00
|
|
|
if len(self.RTTs):
|
|
|
|
return min(self.RTTs)
|
|
|
|
raise NoRttError
|
2021-06-24 17:22:02 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def avg_RTT(self):
|
|
|
|
"""Moyenne du RTT."""
|
2021-07-09 11:46:42 +02:00
|
|
|
if len(self.RTTs):
|
|
|
|
return sum(self.RTTs)/len(self.RTTs)
|
|
|
|
raise NoRttError
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-05 14:17:40 +02:00
|
|
|
@property
|
|
|
|
def RTO(self):
|
2021-07-09 11:46:42 +02:00
|
|
|
return self._RTO
|
2021-07-05 14:17:40 +02:00
|
|
|
return random.uniform(self._RTO, (self._RTO * defines.ACK_RANDOM_FACTOR))
|
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
class SuperviseurLocal(SuperviseurLocalPlaceHolder):
|
2021-06-24 17:22:02 +02:00
|
|
|
"""
|
|
|
|
Class implementant la supervision local de chaque client.
|
|
|
|
"""
|
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
N_MESURE = 2
|
|
|
|
|
2021-06-24 17:22:02 +02:00
|
|
|
def __init__(self, client_CoAP) -> None:
|
|
|
|
super().__init__(client_CoAP)
|
|
|
|
self._dict_envoie = {}
|
2021-07-01 14:42:48 +02:00
|
|
|
self._n_envoie = 0
|
2021-07-09 11:46:42 +02:00
|
|
|
self._n_token = 0
|
|
|
|
self._n_echec = 0
|
2021-06-24 17:22:02 +02:00
|
|
|
|
|
|
|
def envoie_token(self, token) -> None:
|
|
|
|
"""Enregistre l'envoie d'un token
|
|
|
|
|
|
|
|
Args:
|
|
|
|
token (int): Token à enregistrer
|
|
|
|
"""
|
|
|
|
self._n_envoie += 1
|
2021-07-09 11:46:42 +02:00
|
|
|
self._n_token += not(token in self._dict_envoie)
|
2021-07-01 14:42:48 +02:00
|
|
|
self._dict_envoie[token] = time.time()
|
2021-07-09 11:46:42 +02:00
|
|
|
self._taux_retransmition = 1 - self._n_token/self._n_envoie
|
2021-06-24 17:22:02 +02:00
|
|
|
|
|
|
|
def reception_token(self, token) -> None:
|
|
|
|
"""Enregistre l'arrivée d'un token
|
|
|
|
|
|
|
|
Args:
|
|
|
|
token (int): Token à enregister
|
|
|
|
"""
|
2021-07-01 14:42:48 +02:00
|
|
|
if token in self._dict_envoie:
|
|
|
|
rtt = time.time() - self._dict_envoie[token]
|
|
|
|
self._RTTs.append(time.time() - self._dict_envoie[token])
|
2021-07-05 14:17:40 +02:00
|
|
|
# del self._dict_envoie[token]
|
2021-07-01 14:42:48 +02:00
|
|
|
self.callback_new_rtt(rtt)
|
2021-06-24 17:22:02 +02:00
|
|
|
else:
|
2021-07-05 14:17:40 +02:00
|
|
|
pass # raise ValueError("Tokken inconnue")
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
def failed_request(self):
|
|
|
|
self._n_echec += 1
|
|
|
|
return super().failed_request()
|
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
def callback_new_rtt(self, rtt):
|
|
|
|
pass
|
|
|
|
|
2021-07-05 14:17:40 +02:00
|
|
|
def reset(self):
|
|
|
|
self._dict_envoie = {}
|
|
|
|
self._n_envoie = 0
|
2021-07-09 11:46:42 +02:00
|
|
|
self._n_token = 0
|
|
|
|
self._n_echec = 0
|
2021-07-05 14:17:40 +02:00
|
|
|
self._RTTs = []
|
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
|
|
|
|
class SuperviseurLocalFiltre(SuperviseurLocal):
|
2021-07-09 11:46:42 +02:00
|
|
|
|
|
|
|
N_MESURE = 3
|
|
|
|
|
2021-07-05 14:17:40 +02:00
|
|
|
def __init__(self, client_CoAP, rtt_init=0.01, alpha_l=0.01, alpha_s=0.1) -> None:
|
2021-06-24 17:22:02 +02:00
|
|
|
super().__init__(client_CoAP)
|
|
|
|
self.alpha_l = alpha_l
|
|
|
|
self.alpha_s = alpha_s
|
2021-07-01 14:42:48 +02:00
|
|
|
self._RTT_L = rtt_init
|
|
|
|
self._RTT_S = rtt_init
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
def callback_new_rtt(self, rtt):
|
|
|
|
self._RTT_L = rtt*self.alpha_l + (1 - self.alpha_l) * self._RTT_L
|
|
|
|
self._RTT_S = rtt*self.alpha_s + (1 - self.alpha_s) * self._RTT_S
|
|
|
|
return super().callback_new_rtt(rtt)
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
@property
|
|
|
|
def RTT_L(self):
|
|
|
|
return self._RTT_L
|
2021-06-24 17:22:02 +02:00
|
|
|
|
2021-07-01 14:42:48 +02:00
|
|
|
@property
|
|
|
|
def RTT_S(self):
|
|
|
|
return self._RTT_S
|
2021-07-05 14:17:40 +02:00
|
|
|
|
|
|
|
|
|
|
|
class SuperviseurGlobal():
|
2021-07-09 11:46:42 +02:00
|
|
|
nombre_mesure = 3
|
|
|
|
|
2021-07-05 14:17:40 +02:00
|
|
|
def __init__(self, clients, superviseur_type, *superviseur_args) -> None:
|
|
|
|
"""Genère un superviseur global pour la liste de client donnée
|
|
|
|
|
|
|
|
Args:
|
|
|
|
clients (List(HelperClient)): Liste des clients à supervisé
|
|
|
|
superviseur_type (Type): Type de superviseur à utilisé
|
|
|
|
"""
|
|
|
|
self.clients = clients
|
|
|
|
self.superviseurs = [superviseur_type(
|
|
|
|
client, *superviseur_args) for client in clients]
|
2021-07-13 14:53:16 +02:00
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
self._last_state = np.zeros((superviseur_type.N_MESURE, len(clients)))
|
2021-07-05 14:17:40 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def state(self):
|
2021-07-09 11:46:42 +02:00
|
|
|
|
|
|
|
vecteurs = []
|
|
|
|
for n, superviseur in enumerate(self.superviseurs):
|
|
|
|
if isinstance(superviseur, SuperviseurLocalFiltre):
|
2021-07-13 14:53:16 +02:00
|
|
|
try:
|
|
|
|
vecteurs.append(np.array([[superviseur.taux_retransmission, superviseur.min_RTT /
|
|
|
|
superviseur.avg_RTT, superviseur.RTT_S/superviseur.RTT_L]], dtype=np.float32))
|
2021-07-09 11:46:42 +02:00
|
|
|
except NoRttError:
|
2021-07-13 14:53:16 +02:00
|
|
|
vecteurs.append(self._last_state[:, n].reshape((1, 3)))
|
|
|
|
etat = np.concatenate(vecteurs, axis=0).T
|
|
|
|
self._last_state = etat
|
|
|
|
return etat
|
2021-07-09 11:46:42 +02:00
|
|
|
|
|
|
|
def application_action(self, actions):
|
|
|
|
for n, alpha in enumerate(actions):
|
|
|
|
if alpha >= 0:
|
|
|
|
g = 1 + alpha
|
|
|
|
else:
|
|
|
|
g = 1/(1-alpha)
|
|
|
|
self.superviseurs[n]._RTO *= g
|
|
|
|
self.superviseurs[n]._RTO = min([self.superviseurs[n]._RTO, 2])
|
|
|
|
|
|
|
|
def reset(self):
|
|
|
|
[superviseur.reset() for superviseur in self.superviseurs]
|
|
|
|
|
2021-07-13 14:53:16 +02:00
|
|
|
def reset_rto(self):
|
|
|
|
for superviseur in self.superviseurs:
|
|
|
|
superviseur.reset_rto()
|
|
|
|
|
|
|
|
@property
|
|
|
|
def failed(self):
|
|
|
|
return sum([superviseur._n_echec for superviseur in self.superviseurs])
|
|
|
|
|
2021-07-09 11:46:42 +02:00
|
|
|
def qualite(self, n_request, beta_retransmission, beta_equite, beta_RTO):
|
|
|
|
|
|
|
|
n_envoies = np.array([
|
|
|
|
superviseur._n_envoie for superviseur in self.superviseurs])
|
2021-07-13 14:53:16 +02:00
|
|
|
n_tokens = np.array(
|
|
|
|
[superviseur._n_token for superviseur in self.superviseurs])
|
2021-07-09 11:46:42 +02:00
|
|
|
RTOs = np.array([superviseur.RTO for superviseur in self.superviseurs])
|
|
|
|
|
|
|
|
qualite = 0
|
2021-07-13 14:53:16 +02:00
|
|
|
qualite += beta_retransmission * (sum(n_tokens)/sum(n_envoies))
|
2021-07-09 11:46:42 +02:00
|
|
|
qualite += beta_equite * \
|
|
|
|
(sum(n_envoies/n_tokens))**2 / \
|
|
|
|
(len(n_envoies) * sum((n_envoies/n_tokens)**2))
|
2021-07-13 14:53:16 +02:00
|
|
|
qualite += beta_RTO * (2-np.max(RTOs))
|
2021-07-09 11:46:42 +02:00
|
|
|
|
2021-07-13 14:53:16 +02:00
|
|
|
if qualite == np.nan:
|
|
|
|
return 0
|
2021-07-09 11:46:42 +02:00
|
|
|
return qualite
|