Example #1
0
def main():
    nb_connection = 0
    Websock.send_esp_state(1)
    while True:
        Mesh.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while True:
            try:
                Mesh.socket.bind((c.HOST, c.PORT))
                Mesh.socket.listen(5)
            except socket.error as msg:
                print_flush("Socket has failed :", msg)
                time.sleep(0.1)
                continue
            break
        socket_thread = None
        while True:
            print_flush("Socket opened, waiting for connection...")
            conn, addr = Mesh.socket.accept()
            print_flush("Connection accepted with {0}".format(addr))
            if (socket_thread != None):
                socket_thread.close_socket()
                print_flush("The previous connection has been closed")
            socket_thread = Mesh(conn, addr)
            Mesh.print_mesh_info()
            socket_thread.start()
Example #2
0
 def callback(self, ch, method, properties, body):
     Mesh.consummed += 1
     if Mesh.consummed % 100 == 0:  #display mesh status each 100 models received
         Mesh.required_amount = SchedulerState.get_amount()
         Mesh.print_mesh_info()
     # uncommment to reduce the amount of frames send during the esp declaration phase
     # if Mesh.comp < Mesh.required_amount :
     #     print_flush("Not enough pixels on the mesh network to display the model")
     #     return
     if Websock.should_get_deco():
         Listen.deco = json.loads(Websock.get_deco())
     b = body.decode('ascii')
     self.model.set_from_json(b)
     tmp = Websock.get_esp_state()
     if tmp != None and eval(tmp) != self.previous_state:
         Mesh.change_esp_state = True
         print_flush("tmp != None, tmp = {}".format(tmp))
         self.previous_state = eval(tmp)
     else:
         Mesh.change_esp_state = False
     if Mesh.change_esp_state:  # A procedure has started (ie AMA.py is launched) and both the mesh network and the serveur have to be ready
         self.procedures_manager()
     elif (Mesh.ama == 1):  # A procedure is running
         self.ama_care()
     elif (Mesh.addressed):
         # Production mod : all pixels are addressed
         Mesh.sequence = (Mesh.sequence + 1) % 65536
         array = slef.msg.color(self.model._model, Mesh.sequence,
                                Mesh.pixels, Listen.unk)
         self.mesh_conn.send(array)
     else:  # Temporisation required between the launching of AMA.py and the frist model matching the procedure arrives
         print_flush("{} : It is not the time to send colors".format(
             Mesh.consummed))
Example #3
0
    def run(self, params, expires_at=None):
        with self.lock:
            self.model.set_all((0, 0, 0))
            self.send_model()
        users = loads(Websock.get_users())['users']
        if (len(users) == 1):
            self.user = users[0]
        Websock.set_grantUser(self.user)
        self.connectionserver = pika.BlockingConnection(self.paramsserver)
        self.channelserver = self.connectionserver.channel()

        self.channelserver.exchange_declare(exchange='logs',
                                            exchange_type='fanout')

        result = self.channelserver.queue_declare('', exclusive=True)
        queue_name = result.method.queue

        self.channelserver.queue_bind(exchange='logs', queue=queue_name)
        self.channelserver.basic_consume(queue=queue_name,
                                         on_message_callback=self.callback,
                                         auto_ack=True)

        logging.info(
            'Waiting for pixel data on queue "{}".'.format(queue_name))
        self.channelserver.start_consuming()
Example #4
0
def admin_app_quit(user):
    if is_admin(user):
        if (SchedulerState.get_current_app()['name'] == "Snap"):
            Websock.set_grantUser({'id': "turnoff", 'username': "******"})
        removed = SchedulerState.stop_forced_app_request(user)
        return jsonify(removed=removed)
    else:
        abort(403, "Forbidden Bru")
    return '', 204
Example #5
0
 def update(self):
     Websock.send_pos_unk(self.pos_unknown)  #List of pixels to be addressed
     default = self.pixels.pop(
         'default'
     )  #As default is a false pixel, it must be removed before sending the array
     #print_flush(self.pixels)
     Websock.send_pixels(self.pixels)  #list of addressed pixels
     if default:  #if default was removed, it is added again.
         self.pixels['default'] = default
Example #6
0
 def reattributing_indexes(self):
     self.deco = loads(
         Websock.get_deco())  #retrieves the disconnected cards.
     for mac in self.pos_unknown.keys():
         if len(self.deco) > 0:
             # dummy security, should do something in the case of it happenning but dunno what (yet)
             pixel_deco = self.deco.popitem()
             self.pos_unknown[mac] = (
                 (-1, -1), pixel_deco[1][1]
             )  #associate the disconnected card index to the unknown card.
     self.pixels = loads(
         Websock.get_pixels())  #retrieves the current pixel list
     self.pixels['default'] = ((-1, -1), -1)  #adds the fake pixel security.
Example #7
0
    def stop_app(self, c_app, stop_code=None, stop_message=None):
        # flask_log(" ========= STOP_APP ====================")
        if not c_app or 'task_id' not in c_app:
            print_flush('Cannot stop invalid app')
            return

        from tasks.celery import app
        if not c_app.get('is_default', False) and not c_app.get('is_forced', False):
            if stop_code and stop_message and 'userid' in c_app:
                Websock.send_data(stop_code, stop_message, c_app['username'], c_app['userid'])

        app.control.revoke(c_app['task_id'], terminate=True)
        self.frontage.fade_out()
        SchedulerState.set_current_app({})
Example #8
0
 def addressing_procedure(self):
     iteration = 1  #Unused variable - functionality to be implemented later
     #AMA/HAR shall continue as long as there are pixels without known position
     while (len(self.pos_unknown) != 0):
         if self.action == 1:
             #the previous pixel has its right position, considering a new one
             (mac, ((x, y), ind)) = self.pos_unknown.popitem()
         else:
             #the previous position was ill initialize, the same card is considered again, and removed from addressed pixel.
             self.pixels.pop(mac)
             self.pos_unknown.pop(mac)
         self.matriceR(ind,
                       iteration)  #First, send the position request model
         Websock.send_ama_model(
             0)  #Warn the server that the model is in 1D array format
         #print_flush(self.model)
         self.coord = (
             -1, -1
         )  #Reset coordinate in case previous addressing was wrong
         print_flush("Waiting for user to input coordinates...")
         #print_flush([(val[0][0],val[0][1]) for val in self.pixels.values()])
         #print_flush(self.coord)
         #The command under generate an array containing all the (x, y) coordinates of addressed card.
         while ((self.coord in [(val[0][0], val[0][1])
                                for val in self.pixels.values()])):
             #Here is where the default pixel is used : is coordinate of (-1, -1) matches with self.coord, so the program can't progress until user specified new coordinate
             self.send_model()
             time.sleep(0.05)
         #print_flush("apr la boucle d'attente active............................................................;")
         self.pixels[mac] = (self.coord, ind
                             )  #update of the local dictionary
         self.update()  #Update the server dictionnaries
         self.matriceG(ind)  #Send the validation matrix
         Websock.send_ama_model(
             1
         )  # Warns the server that the model must be interpreted as a normal 2D array.
         self.action = 0  #No validation input
         print_flush("Waiting for user validation...")
         while (self.action == 0):
             #wait for the confirmation of the administrator
             self.send_model()
             time.sleep(0.05)
         if self.action == 1:
             #Action is validated by user
             print_flush("Input confirmed")
             iteration += 1
         else:  # the pixel is reput in the pos_unknown dictionary as its position is false
             print_flush("Input canceled")
             self.pos_unknown[mac] = ((x, y), ind)
Example #9
0
    def __init__(self):
        clear_all_task()

        redis.set(SchedulerState.KEY_USERS_Q, '[]')
        redis.set(SchedulerState.KEY_FORCED_APP, 'False')
        Websock.set_grantUser({'id': "turnoff", 'username': "******"})

        self.frontage = Frontage(SchedulerState.get_rows(),
                                 SchedulerState.get_cols())
        self.current_app_state = None
        self.queue = None
        self.count = 0
        self.apps = OrderedDict([(app, globals()[app]('', ''))
                                 for app in get_app_names()])
        SchedulerState.set_registered_apps(self.apps)
Example #10
0
def set_user(user):
    if (not is_admin(user)):
        abort(403, "Forbidden Bru")
    body = request.get_json()
    id = body['selected_client']
    users = (json.loads(Websock.get_users()))['users']
    guser = None
    if (id != "turnoff"):
        for user in users:
            if (user['id'] == id):
                guser = user
        if (guser == None):
            return jsonify(success=False, message="No such client")
    else:
        guser = {'id': "turnoff", 'username': "******"}
    Websock.set_grantUser(guser)
    return jsonify(success=True, message="Client authorized successfully")
Example #11
0
 def ama_care(self):
     #Get the new pixel addressed positions
     tmp = Websock.get_pixels()
     if tmp != None and tmp != {}:
         Mesh.pixels = json.loads(tmp)
     tmp = json.loads(Websock.get_pos_unk())
     if tmp != None:
         Listen.unk = tmp
     #Get the model format to check
     tmp = Websock.get_ama_model()
     if tmp != None:
         self.ama_check = eval(tmp)['ama']
     if self.ama_model():
         # send a COLOR frame only if the model match the expected model
         Mesh.sequence = (Mesh.sequence + 1) % 65536
         array = self.msg.color(self.model._model, Mesh.sequence,
                                Mesh.pixels, Listen.unk, self.ama_check)
         self.mesh_conn.send(array)
Example #12
0
    def stop_app(self, c_app, stop_code=None, stop_message=None):
        # flask_log(" ========= STOP_APP ====================")
        if not c_app or 'task_id' not in c_app:
            return

        from tasks.celery import app
        if not c_app.get('is_default', False) and not c_app.get(
                'is_forced', False):
            if stop_code and stop_message and 'userid' in c_app:
                Websock.send_data(stop_code, stop_message, c_app['username'],
                                  c_app['userid'])

        sleep(0.1)
        # revoke(c_app['task_id'], terminate=True, signal='SIGUSR1')
        # app.control.revoke(c_app['task_id'], terminate=True, signal='SIGUSR1')
        app.control.revoke(c_app['task_id'], terminate=True)
        self.frontage.fade_out()

        sleep(0.05)
Example #13
0
 def callback(self, ch, method, properties, body):
     self.consumme += 1
     listpixels = loads(body.decode('ascii'))
     nuser = loads(Websock.get_grantUser())
     if (nuser.get('id') is None or nuser.get('id') == "turnoff"):
         logging.info("Turn off request")
         self.erase_all()
     elif nuser['id'] != self.user['id']:
         self.user = nuser
         self.erase_all()
         self.set_rgb_matrix(listpixels['pixels'])
     else:
         self.set_rgb_matrix(listpixels['pixels'])
Example #14
0
 def skip_procedure(self):
     #Retrieves the previous configuration
     self.pixels = SchedulerState.get_pixels_dic()
     #print_flush("Before readressing : {0} - {1}".format(self.pixels, self.pos_unknown))
     delete = [key for key in self.pos_unknown
               ]  #retrieves all the mac address of the card to be addressed
     for key in delete:  #Pixel will be matched one on one with those of the Database, according to their mac address.
         value = self.pos_unknown[key]
         pixel = self.pixels.get(key)
         if pixel is None:  #No match is found : user shouldn't have use this... unforeseen behaviour may occur from this point on.
             print_flush("ERROR : using skip is not possible")
         else:
             pixel = (pixel[0], value[1]
                      )  #The old index value is replaced with the new one.
             self.pixels[key] = pixel  #the pixel is then updated
             self.pos_unknown.pop(
                 key
             )  #Finally, the pixel being addressed, so it's removed for the Unkown list.
     #print_flush("After readressing : {0} - {1}".format(self.pixels, self.pos_unknown))
     #Finally, the dictionnary modifications are notified to the server though the Websocket
     Websock.send_pos_unk(self.pos_unknown)
     Websock.send_pixels(self.pixels)
Example #15
0
 def __init__(self, com):
     Thread.__init__(self)
     self.msg = Frame()
     self.com = com
     self.count = 0
     Websock.send_deco(Listen.deco)
     Websock.send_pos_unk(Listen.unk)
     Websock.send_get_deco(False)
Example #16
0
 def procedures_manager(self):
     Mesh.ama += 1
     if Mesh.ama == 1:  #AMA procedure starts
         print_flush("START AMA")
         Mesh.addressed = False
         Mesh.print_mesh_info()
         array = self.msg.ama(c.AMA_INIT)
         self.mesh_conn.send(array)
     elif Mesh.ama == 2:  # Ends adressing procedures
         Mesh.addressed = True
         Mesh.print_mesh_info()
         array = self.msg.ama(c.AMA_COLOR)
         self.mesh_conn.send(array)
         print_flush("END addressing procedure")
     else:  # HAR procedure starts
         print_flush("START HAR")
         Mesh.ama = 1
         Mesh.addressed = False
         Mesh.print_mesh_info()
         array = self.msg.har(Mesh.mac_root, c.STATE_CONF)
         self.mesh_conn.send(array)
         print_flush(Listen.unk.keys(), Listen.deco)
         # The pixel in deco are one by one being forgotten and their index is attributed to one of the unknown
         for mac in Listen.unk.keys():
             if len(Listen.deco) > 0:
                 pixel_deco = Listen.deco.popitem()
                 print_flush("Adding new element")
                 print_flush(pixel_deco)
                 print_flush("Inserted unknwon card at {0}".format(
                     pixel_deco[1][1]))
                 Listen.unk[mac] = ((-1, -1), pixel_deco[1][1])
                 array = self.msg.install_from_mac(mac, pixel_deco[1][1])
                 self.mesh_conn.send(array)
         Websock.send_pos_unk(Listen.unk)
         Mesh.print_mesh_info()
         array = slef.msg.ama(c.AMA_INIT)
         self.mesh_conn.send(array)
Example #17
0
 def update_DB(self):
     if self.pixels.get('default'):  #Remove the fake pixel
         self.pixels.pop('default')
     #Updates the server dictionnaries
     Websock.send_pixels(self.pixels)
     Websock.send_pos_unk({})
     Websock.send_deco(self.deco)
     Websock.send_get_deco()
     #Update DB
     if (
             self.params['mode'] == 'ama' or self.params['mode'] == 'skip'
     ):  # in case of initial addressing, the previous configuration is first deleted.
         SchedulerState.drop_dic()
         print_flush("Database cleaned")
     while (len(self.pixels) !=
            0):  #Pixels are then added one by one to the database
         (mac, ((x, y), ind)) = self.pixels.popitem()
         SchedulerState.add_cell(x, y, mac, ind)
     print_flush("Database updated")
Example #18
0
 def run(self, params, expires_at=None):
     self.start_socket()
     # get necessary informations
     self.rows = SchedulerState.get_rows()
     self.cols = SchedulerState.get_cols()
     # get the pixels to address
     self.pos_unknown = loads(
         Websock.get_pos_unk())  #format {'@mac1' : ((x,j), index), ...}}
     self.params = params
     print_flush("Launched AMA app with {0} parameter".format(
         self.params['mode']))
     if (self.params['mode'] == 'ama'
         ):  # assisted manual addressing : reset the position of all pixels
         Websock.send_pixels({})
     elif (self.params['mode'] == 'rac'):
         # hot assisted readdressing : reattribute the unusued pixel indexes (get from deconnected pixels) without changing already addressed pixels
         self.deco = loads(Websock.get_deco())
         array = []
         for key in self.deco.keys(
         ):  #Generate the list of all free cells for the frontend
             value = self.deco[key]
             array += [value[0]]
         self.send_pixel_down(array)  #sends this list to the frontend
         self.reattributing_indexes()  #update the dictionnaries
     #Put esp root in ADDR or CONF state, depending on the current state of the server : indicate start of procedure
     Websock.send_esp_state(0)
     if self.params['mode'] == 'skip':
         self.skip_procedure()
         sleep(1)
     else:
         self.addressing_procedure()
     #publish on REDIS and save in DB the new pixels dictionary
     self.update_DB()
     #Put ESPs in COLOR state
     Websock.send_esp_state(1)
     self.visual_verification()
     self.wait_to_be_kill()
Example #19
0
 def send_message(self, code):
     Websock.send_data(code, 'Gamelife message', self.username, self.userid)
Example #20
0
 def send_game_over(self):
     Websock.send_data(Fap.CODE_GAME_OVER, 'GAME_OVER', self.username,
                       self.userid)
Example #21
0
 def send_close_app(self):
     Websock.send_data(Fap.CODE_CLOSE_APP, 'CLOSING', self.username,
                       self.userid)
Example #22
0
class Fap(object):
    CODE_CLOSE_APP = 1
    CODE_GAME_OVER = 2
    CODE_EXPIRE = 3
    CODE_EXPIRE_SOON = 4
    CODE_TETRIS_CLEARED_ROW = 10
    CODE_SNAKE_ATE_APPLE = 11

    PARAMS_LIST = []
    PLAYABLE = False
    ACTIVATED = True
    ENABLE = True
    LOCK = RWLock()
    LOCK_WS = RWLock()

    def __init__(self, username, userid):
        SchedulerState.set_expire_soon(False)
        self.max_time = None
        self.params = None
        self.username = username
        self.userid = userid
        self.ws = None
        self.model = Model(SchedulerState.get_rows(),
                           SchedulerState.get_cols())

        credentials = pika.PlainCredentials(
            environ.get('RABBITMQ_DEFAULT_USER'),
            environ.get('RABBITMQ_DEFAULT_PASS'))
        self.connection_params = pika.ConnectionParameters(
            host='rabbit',
            credentials=credentials,
            connection_attempts=100,
            heartbeat=0)
        self.connection = pika.BlockingConnection(self.connection_params)
        #####   Channel used for emiting  model to scheduler
        self.channel = self.connection.channel()
        self.channel.exchange_declare(exchange='model', exchange_type='fanout')

    def run(self):
        raise NotImplementedError("Fap.run() must be overidden")

    def send_close_app(self):
        Websock.send_data(Fap.CODE_CLOSE_APP, 'CLOSING', self.username,
                          self.userid)

    def send_game_over(self):
        Websock.send_data(Fap.CODE_GAME_OVER, 'GAME_OVER', self.username,
                          self.userid)

    def send_message(self, code):
        Websock.send_data(code, 'Gamelife message', self.username, self.userid)

    @staticmethod
    def send_expires(username='', userid=''):
        SchedulerState.set_expire(True)
        Websock.send_data(Fap.CODE_EXPIRE, 'EXPIRE', username, userid)

    @staticmethod
    def send_expires_soon(timeout_in_sec, username='', userid=''):
        SchedulerState.set_expire_soon(True)
        Websock.send_data(Fap.CODE_EXPIRE_SOON, timeout_in_sec, username,
                          userid)

    def start_socket(self):
        self.ws = Websock(self, '0.0.0.0', 33406)
        self.ws.start()

    def flash(self, duration=4., speed=1.5):
        """
        Blocking and self-locking call flashing the current model on and off (mainly for game over)
        :param duration: Approximate duration of flashing in seconds
        :param rate: Rate of flashing in Hz
        """
        rate = Rate(speed)
        t0 = time.time()
        model_id = 0
        # with self._model_lock:
        models_bck = self.model._model.copy()

        model_off = False
        while time.time() - t0 < duration or model_off:
            # with self._model_lock:
            if model_id:
                self.model.set_all('black')
            else:
                self.model._model = models_bck.copy()

            model_id = (model_id + 1) % 2
            model_off = not model_off
            self.send_model()
            rate.sleep()

    def send_model(self):
        if not self.LOCK.acquire_write(2):
            print('Wait for RWLock for too long in Bufferize...Stopping')
            return
        try:
            self.channel.basic_publish(exchange='model',
                                       routing_key='',
                                       body=self.model.json())
        except Exception as e:
            print('FAP Cannot send model to scheduler')
            raise e
        finally:
            self.LOCK.release()

    def jsonify(self):
        struct = {}
        struct['name'] = self.__class__.__name__
        struct['params'] = self.params
        struct['params_list'] = self.PARAMS_LIST
        struct['playable'] = self.PLAYABLE
        struct['activated'] = self.ACTIVATED
        struct['max_time'] = self.max_time
        return struct

    def close(self):
        if self.channel is not None:
            self.channel.close()
        if self.connection is not None:
            self.connection.close()
        if self.ws is not None:
            self.ws.close()
            time.sleep(0.2)
Example #23
0
 def start_socket(self):
     self.ws = Websock(self, '0.0.0.0', 33406)
     self.ws.start()
Example #24
0
 def send_expires(username='', userid=''):
     SchedulerState.set_expire(True)
     Websock.send_data(Fap.CODE_EXPIRE, 'EXPIRE', username, userid)
Example #25
0
 def send_expires_soon(timeout_in_sec, username='', userid=''):
     SchedulerState.set_expire_soon(True)
     Websock.send_data(Fap.CODE_EXPIRE_SOON, timeout_in_sec, username,
                       userid)
Example #26
0
def get_users(user):
    if (not is_admin(user)):
        abort(403, "Forbidden Bru")
    users = (json.loads(Websock.get_users()))['users']
    guser = (json.loads(Websock.get_grantUser()))
    return jsonify(list_clients=users, selected_client=guser)
Example #27
0
 def send_pixel_down(self, positions):
     print_flush("Sending positions to frontend...")
     #print_flush(positions)
     Websock.send_data(positions, 'Pixel down message', self.username,
                       self.userid)
Example #28
0
 def listen(self):
     data = ""
     self.count += 1
     print_flush("{0} Listening... {1}".format(
         self.count, time.asctime(time.localtime(time.time()))))
     # receives 1500 (a wifi frame length)
     data = self.com.recv(1500)
     print_flush("\tReceived : {} ({}) (valid ? {})".format(
         data, len(data), self.msg.is_valid(data)))
     if (data != "" and self.msg.is_valid(data)):
         if (data[c.TYPE] == c.ERROR):
             mac = self.msg.array_to_mac(data[c.DATA + 2:c.DATA + 8])
             print_flush("Pixel {0} has encountered a problem {1}".format(
                 mac, data[c.DATA]))
             if data[c.DATA] == c.ERROR_DECO:
                 # 1) the pixel deconnected has to be removed from the working pixel dictionnary and put in the deconnected pixel one
                 #    If the pixel is not adressed it can be removed from the server knowledges
                 if (Mesh.pixels.get(mac) is not None):
                     Listen.deco[mac] = Mesh.pixels.pop(mac)
                     Websock.send_pixels(Mesh.pixels)
                     Websock.send_deco(Listen.deco)
                 elif (Listen.unk.get(mac) is not None):
                     Listen.unk.pop(mac)
                 array = self.msg.error(data, ack=True)
                 print_flush("Add pixel {0} to Listen.deco : {1}".format(
                     mac, Listen.deco))
             elif data[c.DATA] == c.ERROR_CO:
                 # 1) the new pixel is deal with along with the informations known about it.
                 #    If it has been adressed, it gets to work again without any action from administrator
                 #    Else a administrator action is required. In the former case the pixel goes in working pixels dic
                 #    In the latter it goes in unknown pixels dic to wait for human intervention
                 if mac in Listen.deco:
                     print_flush("Address is in Listen.deco")
                     Mesh.pixels[mac] = Listen.deco.pop(mac)
                     Websock.send_pixels(Mesh.pixels)
                     Websock.send_deco(Listen.deco)
                     array = self.msg.error(data, ack=True)
                 elif mac in Mesh.pixels:
                     print_flush("Address is in Mesh.pixels")
                     array = self.msg.error(data, ack=True)
                 else:
                     # Raising UNK flag
                     Listen.unk[mac] = ((-1, -1), -1)
                     Websock.send_pos_unk(Listen.unk)
                     array = self.msg.error(data, ack=True, unk=True)
             elif data[c.DATA] == c.ERROR_ROOT:
                 # 1) a reelection has occured in the mesh network, the new esp root send a frame to declared herself.
                 #    The mac_root is updated and the known card number is comparted to the one of the root.
                 Mesh.mac_root = mac
                 nb_card = (data[c.DATA + 1] & 0xF0) >> 4
                 print_flush("on dit qu'il y a {}".format(nb_card))
                 # 2) If the error has occured because of the mesh network  : the routing table is sent to the newly elected esp root
                 #    Else it was due to the sever wich takes the nb_pixels has granted and considered pixels has addressed.
                 if Mesh.comp >= nb_card:
                     self.send_table(data[c.DATA + 1] & 0x0F)
                 else:
                     Mesh.comp = nb_card
                     Mesh.addressed = True
                     array = self.msg.har(Mesh.mac_root,
                                          data[c.DATA + 1] & 0x0F)
                     self.com.send(array)
                 return
             else:
                 print_flush("Unkown message type")
             print_flush(
                 "Updates  Listen.deco {0} \n Updates Listen.unk {1}".
                 format(Listen.deco, Listen.unk))
             # 2) Once the ERROR has been managed and informations updated, the esp root is informed of its fate
             self.com.send(array)
             print_flush("acquitted")
         elif (data[c.TYPE] == c.BEACON):
             # 1) BEACON are only received during configuration phase. The esp declared itself one-by-one.
             #   Along with their declarations, they are stocked in unk dic wich is sent on Reddis at each new esp BEACON.
             #   It is necessary to do so because their is no way to known in advance how many esp will be in the mesh network.
             mac = self.msg.array_to_mac(data[c.DATA:c.DATA + 6])
             print_flush("Pixel {0} is declaring itself".format(mac))
             if (Mesh.comp == 0):
                 # The first to declared itself is the esp root
                 Mesh.mac_root = mac
             if Listen.unk.get(mac) != None:
                 # an ESP is only considered once
                 print_flush("But it has already be declared ")
                 pass
             Listen.unk[mac] = ((-1, -1), Mesh.comp)
             Websock.send_pos_unk(Listen.unk)
             array = self.msg.install(data, Mesh.comp)
             Mesh.comp += 1
             # 2) A INSTALL Frame is sent to the esp root for it to update its routing table and acknoledge the esp first sender
             self.com.send(array)
         else:
             print_flush("received unintersting message...")