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)
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))
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
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()
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
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
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
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)
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()
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()
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()
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()
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({})
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()
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")
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")
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()
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)
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)
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']))
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))
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))
def send_pixels(pixels): print_flush( "###############################################################################" ) print_flush("Send : [pixels={0}]".format(pixels)) print_flush( "###############################################################################" ) redis.set(PIXELS, json.dumps(pixels))
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}))
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()
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))
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))
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 }))
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
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()