From d0a49e744e618d390b5b7756c6906998c5d54cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9opold=20Cl=C3=A9ment?= Date: Thu, 24 Jun 2021 17:22:02 +0200 Subject: [PATCH] demo fonctionelle Superviseur basique et filtrage --- coapthon/client/coap.py | 6 ++ coapthon/client/helperclient.py | 1 + coapthon/client/superviseur_local.py | 108 +++++++++++++++++++++++++++ demo_superviseur.py | 57 ++++++++++++++ 4 files changed, 172 insertions(+) create mode 100644 coapthon/client/superviseur_local.py create mode 100644 demo_superviseur.py diff --git a/coapthon/client/coap.py b/coapthon/client/coap.py index 0bf3e28..8155a7c 100644 --- a/coapthon/client/coap.py +++ b/coapthon/client/coap.py @@ -1,3 +1,4 @@ + import logging import random import socket @@ -15,6 +16,7 @@ from coapthon.messages.request import Request from coapthon.messages.response import Response from coapthon.serializer import Serializer +from coapthon.client.superviseur_local import SuperviseurLocalBase __author__ = 'Giacomo Tanganelli' @@ -65,6 +67,8 @@ class CoAP(object): self._receiver_thread = None + self.superviseur = SuperviseurLocalBase(self) + def purge_transactions(self, timeout_time=defines.EXCHANGE_LIFETIME): """ Clean old transactions @@ -166,6 +170,7 @@ class CoAP(object): try: self._socket.sendto(raw_message, (host, port)) + self.superviseur.envoie_message(message) except Exception as e: if self._cb_ignore_write_exception is not None and isinstance(self._cb_ignore_write_exception, collections.Callable): if not self._cb_ignore_write_exception(e, self): @@ -273,6 +278,7 @@ class CoAP(object): source = (host, port) message = serializer.deserialize(datagram, source) + self.superviseur.reception_message(message) if isinstance(message, Response): logger.info("receive_datagram - " + str(message)) diff --git a/coapthon/client/helperclient.py b/coapthon/client/helperclient.py index eb79191..2e83102 100644 --- a/coapthon/client/helperclient.py +++ b/coapthon/client/helperclient.py @@ -28,6 +28,7 @@ class HelperClient(object): self.protocol = CoAP(self.server, random.randint(1, 65535), self._wait_response, sock=sock, cb_ignore_read_exception=cb_ignore_read_exception, cb_ignore_write_exception=cb_ignore_write_exception) self.queue = Queue() + self.superviseur = self.protocol.superviseur def _wait_response(self, message): """ diff --git a/coapthon/client/superviseur_local.py b/coapthon/client/superviseur_local.py new file mode 100644 index 0000000..a57e62a --- /dev/null +++ b/coapthon/client/superviseur_local.py @@ -0,0 +1,108 @@ +import time + + +class SuperviseurLocalBase(): + """Class de base pour le superviseur + """ + def __init__(self, client_CoAP) -> None: + self.client = client_CoAP + self._n_tokken = 0 + self._n_envoie = 0 + + def envoie_message(self, message) -> None: + self.envoie_token(message.token) + + def reception_message(self, message) -> None: + self.reception_token(message.token) + + @property + def min_RTT(self): + """Valeur minimum du RTT""" + return min(self.RTTs) + + @property + def avg_RTT(self): + """Moyenne du RTT.""" + return sum(self.RTTs)/len(self.RTTs) + + @property + def tau_retransmission(self): + """Rapport du nombre de message correspondant à des restransmission sur le nombre de message total.""" + return 1 - self._n_tokken/self._n_envoie + + +class SuperviseurLocal(SuperviseurLocalBase): + """ + Class implementant la supervision local de chaque client. + """ + + def __init__(self, client_CoAP) -> None: + super().__init__(client_CoAP) + self._dict_envoie = {} + self._dict_reception = {} + + @property + def RTTs(self): + RTTs = [] + for token in self._dict_reception: + if token in self._dict_envoie: + RTTs.append( + self._dict_reception[token][0] - self._dict_envoie[token][-1]) + return RTTs + + def envoie_token(self, token) -> None: + """Enregistre l'envoie d'un token + + Args: + token (int): Token à enregistrer + """ + self._n_envoie += 1 + if token in self._dict_envoie: + self._dict_envoie[token].append(time.time()) + else: + self._n_tokken += 1 + self._dict_envoie[token] = [time.time()] + + def reception_token(self, token) -> None: + """Enregistre l'arrivée d'un token + + Args: + token (int): Token à enregister + """ + if token in self._dict_reception: + self._dict_reception[token].append(time.time()) + else: + self._dict_reception[token] = [time.time()] + + +class SuperviseurLocalFiltre(SuperviseurLocalBase): + def __init__(self, client_CoAP, rtt_init=0.001, alpha_l=0.01, alpha_s=0.1) -> None: + super().__init__(client_CoAP) + self._dict_envoie = {} + self.alpha_l = alpha_l + self.alpha_s = alpha_s + self.RTT_L = rtt_init + self.RTT_S = rtt_init + self.RTTs = [] + + def envoie_token(self, token) -> None: + """Enregistre l'envoie d'un token + + Args: + token (int): Token à enregistrer + """ + self._n_envoie += 1 + if token in self._dict_envoie: + self._dict_envoie[token].append(time.time()) + else: + self._n_tokken += 1 + self._dict_envoie[token] = [time.time()] + + def reception_token(self, token) -> None: + if token in self._dict_envoie: + r = time.time() - self._dict_envoie[token][-1] + self.RTTs.append(r) + self.RTT_L = r*self.alpha_l + (1 - self.alpha_l) * self.RTT_L + self.RTT_S = r*self.alpha_s + (1 - self.alpha_s) * self.RTT_S + else: + raise ValueError diff --git a/demo_superviseur.py b/demo_superviseur.py new file mode 100644 index 0000000..2d365c0 --- /dev/null +++ b/demo_superviseur.py @@ -0,0 +1,57 @@ +import matplotlib.pyplot as plt +import socket +import time +from coapthon.client import superviseur_local + +from coapthon.client.helperclient import HelperClient +from coapthon.client.superviseur_local import SuperviseurLocal, SuperviseurLocalFiltre +from coapthon.utils import parse_uri + + +host, port, path = parse_uri("coap://localhost:5683/basic") +try: + tmp = socket.gethostbyname(host) + host = tmp +except socket.gaierror: + pass +print('start client') +client = HelperClient(server=(host, port)) +print('client started') +client.protocol.superviseur = SuperviseurLocalFiltre(client) +super = client.protocol.superviseur + +rtt_l = [] +rtt_s = [] + +for n_rep in range(1000): + # print('rep{}'.format(n_rep)) + response = client.get(path) + rtt_l.append(super.RTT_L) + rtt_s.append(super.RTT_S) + # time.sleep(1) + # print("{} : \n{}".format(n_rep, response.pretty_print())) +client.stop() + +print(super.min_RTT, super.avg_RTT, super.tau_retransmission) + +fig, axs = plt.subplots(2) + +axs[0].hist(super.RTTs, 100, density=True) + +axs[0].set_xlabel('RTT (s)') +axs[0].set_xlim(left=0) + +# axs[1].step(range(1000), super.RTTs, where='post', label='$RTT$') +axs[1].plot(rtt_l, label="$RTT_L$") +axs[1].plot(rtt_s, label="$RTT_S$") + + +axs[1].set_ylim(bottom=0) +axs[1].set_xlabel('Nombre de message') +axs[1].set_ylabel('RTT (s)') +axs[1].legend() + +fig.suptitle('Resultat sur un serveur local') + +fig.tight_layout() +fig.savefig('demo.png')