コード例 #1
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
 def __init__(self, conn, addr):
     Thread.__init__(self)
     print_flush("Pixels :", Mesh.pixels)
     #Manage adressing procedures
     Mesh.addressed = not (Mesh.pixels == {})
     self.ama_check = 0
     self.previous_state = 1
     self.model = Model(SchedulerState.get_rows(),
                        SchedulerState.get_cols())
     #Communication with mesh network config
     self.msg = Frame()
     self.mesh_conn = conn
     self.mesh_addr = addr
     self.l = Listen(conn)
     self.l.start()
     self.stopped = False
     #Communication with RabbitMQ config
     self.channel = None
     self.connection = None
     credentials = pika.PlainCredentials(
         os.environ['RABBITMQ_DEFAULT_USER'],
         os.environ['RABBITMQ_DEFAULT_PASS'])
     self.params = pika.ConnectionParameters(host='rabbit',
                                             credentials=credentials,
                                             heartbeat=0)
コード例 #2
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
 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))
コード例 #3
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
    def run(self):
        try:
            self.connection = pika.BlockingConnection(self.params)
            self.channel = self.connection.channel()
            self.channel.exchange_declare(exchange='pixels',
                                          exchange_type='fanout')

            result = self.channel.queue_declare(exclusive=True,
                                                arguments={"x-max-length": 1})
            queue_name = result.method.queue

            self.channel.queue_bind(exchange='pixels', queue=queue_name)
            self.channel.basic_consume(self.callback,
                                       queue=queue_name,
                                       no_ack=True)
            Mesh.print_mesh_info()
            print_flush(
                'Waiting for pixel data on queue "{}".'.format(queue_name))

            self.channel.start_consuming()
        except Exception as e:
            if self.channel is not None:
                self.channel.close()
            if self.connection is not None:
                self.connection.close()
            raise e
コード例 #4
0
 def stop_current_app_start_next(self, queue, c_app, next_app):
     SchedulerState.set_event_lock(True)
     print_flush('## Revoking app [stop_current_app_start_next]')
     self.stop_app(c_app, Fap.CODE_EXPIRE, 'Someone else turn')
     # Start app
     print_flush("## Starting {} [stop_current_app_start_next]".format(next_app['name']))
     start_fap.apply_async(args=[next_app], queue='userapp')
     SchedulerState.wait_task_to_start()
コード例 #5
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
 def close_socket(self):
     print_flush("exiting thread, closing connection")
     if self.mesh_conn is not None:
         self.mesh_conn.close()
     if self.channel is not None:
         self.channel.close()
     if self.connection is not None:
         self.connection.close()
     print_flush("Closed connection, exiting thread...")
     self.stopped = True
コード例 #6
0
 def visual_verification(self):
     print_flush(SchedulerState.get_pixels_dic())
     for i in range(self.rows):
         for j in range(self.cols):
             self.model.set_pixel(i, j, name_to_rgb('red'))
             waiting = 0
             while waiting < 10:
                 self.send_model()
                 time.sleep(0.1)
                 waiting += 1
コード例 #7
0
ファイル: snake.py プロジェクト: Roudoudoux/frontage
    def __init__(self, username, userid):
        self.PARAMS_LIST = {'speed': 0.15, 'food': 1}

        Fap.__init__(self, username, userid)
        print_flush("Init of SNAKE", self.model.height, self.model.width)

        self.DIRECTION = DOWN
        self.HEAD = (0, 0)
        self.queue = [self.HEAD]
        self.FOOD_POSITIONS = {}
        self.rate = 2
コード例 #8
0
ファイル: snake.py プロジェクト: Roudoudoux/frontage
    def spawn_food(self, quantity=4):
        for _ in range(0, quantity):
            while True:
                f = (random.randint(0, self.model.height - 1),
                     random.randint(0, self.model.width - 1))
                if f not in self.queue and f not in self.FOOD_POSITIONS:
                    print_flush("Muri desu yo!")
                    break
            self.FOOD_POSITIONS[f] = True
            print_flush("New food generated")

            self.model.set_pixel(f[0], f[1], self.FOOD_COLOR)
コード例 #9
0
ファイル: tetris.py プロジェクト: Roudoudoux/frontage
 def __init__(self, username, userid):
     super(Tetris, self).__init__(username, userid)
     self.PARAMS_LIST = {'speed': 0.15}
     self.colors = [
         'black', 'deeppink', 'green', 'darkred', 'orangered', 'darkblue',
         'cyan', 'yellow'
     ]
     self.next_stone = tetris_shapes[rand(len(tetris_shapes))]
     Tetris.cols = SchedulerState.get_cols()
     Tetris.rows = SchedulerState.get_rows()
     print_flush("Init of TETORISU", self.model.height, self.model.width)
     self.init_game()
コード例 #10
0
    def start_default_app(self):
        default_scheduled_app = SchedulerState.get_next_default_app()
        if default_scheduled_app:
            # if not default_scheduled_app['expires'] or default_scheduled_app['expires'] == 0: # TODO restore when each default app has a duration
            #    default_scheduled_app['expires'] = SchedulerState.get_default_fap_lifetime()
            default_scheduled_app['expires'] = SchedulerState.get_default_fap_lifetime()
            default_scheduled_app['default_params']['name'] = default_scheduled_app['name']  # Fix for Colors (see TODO refactor in colors.py)
            SchedulerState.set_event_lock(True)

            print_flush("## Starting {} [DEFAULT]".format(default_scheduled_app['name']))
            start_default_fap.apply_async(args=[default_scheduled_app], queue='userapp')
            SchedulerState.wait_task_to_start()
コード例 #11
0
ファイル: snake.py プロジェクト: Roudoudoux/frontage
    def run(self, params, expires_at=None):
        self.start_socket()

        if not params:
            params = {}
        self.params = params
        self.rate_increase = params.get('speed', self.PARAMS_LIST.get('speed'))
        self.start_food = params.get('food', self.PARAMS_LIST.get('food'))
        rate = Rate(self.rate)

        self.model.set_all(self.BG_COLOR)
        self.model.set_pixel(self.HEAD[0], self.HEAD[1], self.PIXEL_COLOR)
        self.spawn_food(self.start_food)
        for x, y in self.FOOD_POSITIONS:
            self.model.set_pixel(x, y, self.FOOD_COLOR)
        self.send_model()
        print_flush("Started party with", self.start_food, "food.")

        while True:
            rate.sleep_dur = 1.0 / self.rate
            print_flush("Snake = ", self.queue, "; Apple = ",
                        self.FOOD_POSITIONS)
            with self.model:
                new_pos = ((self.HEAD[0] + self.DIRECTION[0]) %
                           self.model.height,
                           (self.HEAD[1] + self.DIRECTION[1]) %
                           self.model.width)

                if new_pos in self.FOOD_POSITIONS:
                    self.send_message(Fap.CODE_SNAKE_ATE_APPLE)
                    del self.FOOD_POSITIONS[new_pos]
                    self.spawn_food(1)
                    self.rate += self.rate_increase
                    self.process_extras()
                else:
                    x, y = self.queue.pop(0)
                    self.model.set_pixel(x, y, self.BG_COLOR)
                    self.process_extras(x, y)

                if new_pos in self.queue:
                    # Game Over !!
                    self.send_model()
                    self.game_over()
                    return
                else:
                    self.HEAD = new_pos
                    self.model.set_pixel(new_pos[0], new_pos[1],
                                         self.PIXEL_COLOR)
                    self.queue.append(new_pos)
                    self.send_model()
                    rate.sleep()
コード例 #12
0
    def add_cell(x, y, mac_address, ind):
        print_flush("Considering {0} at (({1}, {2}), {3})".format(
            mac_address, x, y, ind))
        session = session_factory()
        table = session.query(CellTableModel).all()
        isInTable = False
        for cell in table:
            if (cell.X == x and cell.Y == y):
                print_flush("Found its position : updating mac and ind...")
                isInTable = True
                cell.MacAddress = mac_address
                cell.Ind = ind
            elif (cell.MacAddress == mac_address):
                print_flush("Found its mac : updating position and ind...")
                isInTable = True
                cell.Ind = ind
                cell.X == x
                cell.Y == y
        if (isInTable == False):
            print_flush("Not found : adding to table")
            cell = CellTableModel(x, y, mac_address, ind)
            session.add(cell)
            session.commit()

        session.close()
コード例 #13
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({})
コード例 #14
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
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()
コード例 #15
0
    def handle_message(self, json_data, path=None):
        print_flush(json_data)
        #Retrieving and extracting the message
        if json_data is None:
            raise ValueError("Error : empty message received from WebSocket")
        elif isinstance(json_data, str):
            data = loads(json_data)
        else:
            raise ValueError("Incorrect payload value type for AMA Fapp")

        if (data.get('x') != None):  #Coordinates were sent for the pixel
            x = int(data['x'])
            y = int(data['y'])
            self.coord = (y, x)  #Updating the pixel coordinate.
        elif (data.get('action') !=
              None):  #User specified validity of their input
            self.action = data.get('action')
        else:
            print_flush("Received unknown message from frontend")
コード例 #16
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")
コード例 #17
0
 def run(self):
     # last_state = False
     # we reset the value
     SchedulerState.set_frontage_on(True)
     SchedulerState.set_enable_state(SchedulerState.get_enable_state())
     # usable = SchedulerState.usable()
     print_flush('[SCHEDULER] Entering loop')
     self.frontage.start()
     try:
         while True:
             if SchedulerState.is_event_lock():
                 print_flush('Locked')
             else:
                 self.run_scheduler()
                 self.print_scheduler_info()
             sleep(0.1)
     except:
         raise
     finally:
         pass
         self.frontage.close()
コード例 #18
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)
コード例 #19
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)
コード例 #20
0
ファイル: drawing.py プロジェクト: Roudoudoux/frontage
    def handle_message(self, json_data, path=None):  # noqa
        print_flush("Received something :3")
        if json_data is None:
            raise ValueError("Error : message received on websocket is empty.")
        elif isinstance(json_data, str):
            data = loads(json_data)
        else:
            raise ValueError("Incorrect payload value type for Drawing Fapp")

        pixel = data['pixel']
        color = data['color']

        px_x = int(pixel['x'])
        px_y = int(pixel['y'])

        assert (isinstance(color['red'], int) and 0 <= color['red'] <= 255)
        assert (isinstance(color['green'], int) and 0 <= color['green'] <= 255)
        assert (isinstance(color['blue'], int) and 0 <= color['blue'] <= 255)

        self.model.set_pixel(
            px_x, px_y,
            rgb255_to_rgb(color['red'], color['green'], color['blue']))
コード例 #21
0
 def send_pos_unk(pos_unknown):
     print_flush(
         "###############################################################################"
     )
     print_flush("Send : [pos_unknown={0}]".format(pos_unknown))
     print_flush(
         "###############################################################################"
     )
     redis.set(POS_UNK, json.dumps(pos_unknown))
コード例 #22
0
 def send_esp_state(esp_state):
     print_flush(
         "###############################################################################"
     )
     print_flush("Send : [esp_state = {0}]".format(esp_state))
     print_flush(
         "###############################################################################"
     )
     redis.set(ADDR, json.dumps(esp_state))
コード例 #23
0
 def send_pixels(pixels):
     print_flush(
         "###############################################################################"
     )
     print_flush("Send : [pixels={0}]".format(pixels))
     print_flush(
         "###############################################################################"
     )
     redis.set(PIXELS, json.dumps(pixels))
コード例 #24
0
 def send_ama_model(ama_model):
     print_flush(
         "###############################################################################"
     )
     print_flush("Send : [matrix type = {0}]".format(ama_model))
     print_flush(
         "###############################################################################"
     )
     redis.set(AMA, json.dumps({'ama': ama_model}))
コード例 #25
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()
コード例 #26
0
 def send_deco(deconnected_pixels):
     print_flush(
         "###############################################################################"
     )
     print_flush(
         "Send : [pixels_deconnected={0}]".format(deconnected_pixels))
     print_flush(
         "###############################################################################"
     )
     redis.set(DECO, json.dumps(deconnected_pixels))
コード例 #27
0
ファイル: mesh.py プロジェクト: Roudoudoux/frontage
 def send_table(self, previous_state):
     print_flush("Sending routing table... Step 1 achieved.")
     array = self.msg.har(Mesh.mac_root, c.STATE_CONF)
     self.com.send(array)
     # sorting values in acsending order as required by ESP algorithm
     root_val = Mesh.pixels[Mesh.mac_root]
     card_list = [None] * Mesh.comp
     for val in Mesh.pixels:
         ((i, j), ind) = Mesh.pixels.get(val)
         card_list[ind] = ((i, j), val)
     for val in Listen.deco:
         ((i, j), ind) = Listen.deco.get(val)
         card_list[ind] = ((i, j), val)
     # sending INSTALL frame one by one
     for ind, value in enumerate(card_list):
         ((i, j), val) = value
         print_flush("on envoie INSTALL pour {}".format(ind))
         array = self.msg.install_from_mac(val, ind)
         print_flush("voici l'array {}".format(array))
         self.com.send(array)
     # sending ERROR GO_TO
     array = self.msg.har(Mesh.mac_root, previous_state)
     self.com.send(array)
     print_flush("Routing table has been sent to {}".format(Mesh.mac_root))
コード例 #28
0
 def send_data(code, message, username='', userid=''):
     print_flush(
         "###############################################################################"
     )
     print_flush(
         "Send : [code={0}] [message={1}] [username={2}] [userid={3}]".
         format(code, message, username, userid))
     print_flush(
         "###############################################################################"
     )
     redis.set(
         KEY_WS_SEND,
         json.dumps({
             'code': code,
             'message': message,
             'username': username,
             'userid': userid
         }))
コード例 #29
0
 def print_scheduler_info(self):
     if self.count % 10 == 0:
         self.count = 0
         print_flush(" ========== Scheduling ==========")
         print_flush("-------- Enable State")
         print_flush(SchedulerState.get_enable_state())
         print_flush("-------- Is Frontage Up?")
         print_flush(SchedulerState.is_frontage_on())
         print_flush("-------- Usable?")
         print_flush(SchedulerState.usable())
         print_flush("-------- Current App")
         print_flush(SchedulerState.get_current_app())
         print_flush('Forced App ?', SchedulerState.get_forced_app())
         print_flush("---------- Waiting Queue")
         print_flush(SchedulerState.get_user_app_queue())
         if SchedulerState.get_enable_state() == 'scheduled':
             print_flush("---------- Scheduled ON")
             print_flush(SchedulerState.get_scheduled_on_time())
             print_flush("---------- Scheduled OFF")
             print_flush(SchedulerState.get_scheduled_off_time())
     self.count += 1
コード例 #30
0
    def check_app_scheduler(self):
        # check keep alive app (in user waiting app Q)
        self.keep_alive_waiting_app()

        # collect usefull struct & data
        queue = SchedulerState.get_user_app_queue()  # User waiting app
        c_app = SchedulerState.get_current_app()  # Current running app
        now = datetime.datetime.now()

        forced_app = SchedulerState.get_forced_app_request()

        # Is a app running ?
        if c_app:
            close_request, close_userid = SchedulerState.get_close_app_request()
            if close_request:
                message = Fap.CODE_CLOSE_APP if close_userid != c_app['userid'] else None
                print_flush('## Stopping app upon user reques [check_app_scheduler]')
                self.stop_app(c_app, message, 'Executing requested app closure')
                redis.set(SchedulerState.KEY_STOP_APP_REQUEST, '{}')
                return
            if len(forced_app) > 0 and not SchedulerState.get_forced_app():
                print_flush('## Closing previous app for forced one [check_app_scheduler]')
                SchedulerState.clear_user_app_queue()
                self.stop_app(c_app, Fap.CODE_CLOSE_APP, 'The admin started a forced app')
                return
            # do we kill an old app no used ? ?
            if self.keep_alive_current_app(c_app):
                return
            # is expire soon ?
            if not c_app.get('is_default', False) and now > (datetime.datetime.strptime(c_app['expire_at'], "%Y-%m-%d %H:%M:%S.%f") - datetime.timedelta(seconds=EXPIRE_SOON_DELAY)):
                if not SchedulerState.get_expire_soon():
                    Fap.send_expires_soon(EXPIRE_SOON_DELAY, c_app['username'], c_app['userid'])
            # is the current_app expired ?
            if self.app_is_expired(c_app) or c_app.get('is_default', False):
                # is the current_app a FORCED_APP ?
                if SchedulerState.get_forced_app():
                    print_flush('## Stopping expired forced app [check_app_scheduler]')
                    self.stop_app(c_app)
                    return
                # is some user-app are waiting in queue ?
                if len(queue) > 0:
                    next_app = queue[0]
                    self.stop_current_app_start_next(queue, c_app, next_app)
                    return
                else:
                    # is a defautl scheduled app ?
                    if c_app.get('is_default', False) and self.app_is_expired(c_app):
                        print_flush('## Stopping expired default scheduled app [check_app_scheduler]')
                        self.stop_app(c_app)
                        return
                    # it's a USER_APP, we let it running, do nothing
                    else:
                        pass
        else:
            if len(forced_app) > 0 and not SchedulerState.get_forced_app():
                print_flush("## Starting {} [FORCED]".format(forced_app['name']))
                SchedulerState.set_event_lock(True)
                SchedulerState.clear_forced_app_request()
                start_forced_fap.apply_async(args=[forced_app], queue='userapp')
                redis.set(SchedulerState.KEY_FORCED_APP, 'True')
                return
            # is an user-app waiting in queue to be started ?
            elif len(queue) > 0:
                SchedulerState.set_event_lock(True)
                start_fap.apply_async(args=[queue[0]], queue='userapp')
                print_flush(" Starting {} [QUEUE]".format(queue[0]['name']))
                return
            else:
                return self.start_default_app()