class _NetworkNode(NetworkInterface): """ Communication node Creates Pyre node and handles all communication. """ def __init__(self, format: DataFormat, context=None, name=None, headers=(), callbacks=()): self._name = name self._format = format self._headers = headers self._pyre_node = None self._context = context or zmq.Context() self._sensors_by_host = {} self._callbacks = [self._on_event] + list(callbacks) # Public NetworkInterface API @property def has_events(self) -> bool: return self.running and self._pyre_node.socket().get( zmq.EVENTS) & zmq.POLLIN @property def running(self) -> bool: return bool(self._pyre_node) @property def sensors(self) -> typing.Mapping[str, NetworkSensor]: sensors = {} for sensor in self._sensors_by_host.values(): sensors.update(sensor) return sensors @property def callbacks(self) -> typing.Iterable[NetworkEventCallback]: return self._callbacks @callbacks.setter def callbacks(self, value: typing.Iterable[NetworkEventCallback]): self._callbacks = value def start(self): # Setup node logger.debug("Starting network...") self._pyre_node = Pyre(self._name) self._name = self._pyre_node.name() for header in self._headers: self._pyre_node.set_header(*header) self._pyre_node.join(self._group) self._pyre_node.start() def whisper(self, peer, msg_p): if self._format == DataFormat.V3: return # no-op elif self._format == DataFormat.V4: self._pyre_node.whisper(peer, msg_p) else: raise NotImplementedError() def rejoin(self): for sensor_uuid, sensor in list(self.sensors.items()): self._execute_callbacks({ "subject": "detach", "sensor_uuid": sensor_uuid, "sensor_name": sensor["sensor_name"], "host_uuid": sensor["host_uuid"], "host_name": sensor["host_name"], }) self._pyre_node.leave(self._group) self._pyre_node.join(self._group) def stop(self): logger.debug("Stopping network...") self._pyre_node.leave(self._group) self._pyre_node.stop() self._pyre_node = None def handle_event(self): if not self.has_events: return event = PyreEvent(self._pyre_node) uuid = event.peer_uuid if event.type == "SHOUT" or event.type == "WHISPER": try: payload = event.msg.pop(0).decode() msg = serial.loads(payload) msg["subject"] msg["sensor_uuid"] msg["host_uuid"] = event.peer_uuid.hex msg["host_name"] = event.peer_name except serial.decoder.JSONDecodeError: logger.warning('Malformatted message: "{}"'.format(payload)) except (ValueError, KeyError): logger.warning("Malformatted message: {}".format(msg)) except Exception: logger.debug(tb.format_exc()) else: if msg["subject"] == "attach": if self.sensors.get(msg["sensor_uuid"]): # Sensor already attached. Drop event return sensor_type = SensorType.supported_sensor_type_from_str( msg["sensor_type"]) if sensor_type is None: logger.debug("Unsupported sensor type: {}".format( msg["sensor_type"])) return elif msg["subject"] == "detach": sensor_entry = self.sensors.get(msg["sensor_uuid"]) # Check if sensor has been detached already if not sensor_entry: return msg.update(sensor_entry) else: logger.debug("Unknown host message: {}".format(msg)) return self._execute_callbacks(msg) elif event.type == "JOIN": # possible values for `group_version` # - [<unrelated group>] # - [<unrelated group>, <unrelated version>] # - ['pupil-mobile'] # - ['pupil-mobile', <version>] group_version = event.group.split("-v") group = group_version[0] version = group_version[1] if len(group_version) > 1 else "0" elif event.type == "EXIT": gone_peer = event.peer_uuid.hex for host_uuid, sensors in list(self._sensors_by_host.items()): if host_uuid != gone_peer: continue for sensor_uuid, sensor in list(sensors.items()): self._execute_callbacks({ "subject": "detach", "sensor_uuid": sensor_uuid, "sensor_name": sensor["sensor_name"], "host_uuid": host_uuid, "host_name": sensor["host_name"], }) else: logger.debug("Dropping {}".format(event)) def sensor( self, sensor_uuid: str, callbacks: typing.Iterable[NetworkEventCallback] = () ) -> Sensor: try: sensor_settings = self.sensors[sensor_uuid].copy() except KeyError: raise ValueError( '"{}" is not an available sensor id.'.format(sensor_uuid)) sensor_type_str = sensor_settings.pop("sensor_type", "unknown") sensor_type = SensorType.supported_sensor_type_from_str( sensor_type_str) if sensor_type is None: raise ValueError('Sensor of type "{}" is not supported.'.format( sensor_type_str)) return Sensor.create_sensor( sensor_type=sensor_type, format=self._format, context=self._context, callbacks=callbacks, **sensor_settings, ) # Public def __str__(self): return "<{} {} [{}]>".format(__name__, self._name, self._pyre_node.uuid().hex) # Private @property def _group(self) -> str: return group_name_from_format(self._format) def _execute_callbacks(self, event): for callback in self.callbacks: callback(self, event) def _on_event(self, caller, event): if event["subject"] == "attach": subject_less = event.copy() del subject_less["subject"] host_uuid = event["host_uuid"] host_sensor = {event["sensor_uuid"]: subject_less} try: self._sensors_by_host[host_uuid].update(host_sensor) except KeyError: self._sensors_by_host[host_uuid] = host_sensor logger.debug(f'Attached {host_uuid}.{event["sensor_uuid"]}') elif event["subject"] == "detach": for host_uuid, sensors in self._sensors_by_host.items(): try: del sensors[event["sensor_uuid"]] logger.debug( f'Detached {host_uuid}.{event["sensor_uuid"]}') except KeyError: pass hosts_to_remove = [ host_uuid for host_uuid, sensors in self._sensors_by_host.items() if len(sensors) == 0 ] for host_uuid in hosts_to_remove: del self._sensors_by_host[host_uuid]
def chat_task(ctx, pipe): print("Game started") print("Name: %s" % NAME) connected_players = 1 network_players = 1 leave_counter = 0 #Set up node for the game n = Pyre("") n.set_header("header_name", NAME) #Join the group n.join(GROUPNAME) #Start broadcasting node n.start() # Set up poller poller = zmq.Poller() poller.register( pipe, zmq.POLLIN ) #Local pipe (contains commands/messages we send through terminal) poller.register(n.socket(), zmq.POLLIN) # A while loop constantly polls for new items = PULL system while True: #Wait for new message to be polled. This function blocks until there is a new message items = dict(poller.poll()) #This are messages from ourselves if pipe in items: message_pipe = pipe.recv() if message_pipe.decode('utf-8') == STOP_COMMAND: break #check if the message is a number elif message_pipe.decode( 'utf-8').isdigit() == True and yourturn == True: #variable to keep the loop going until a correct number is given status = True #check which symbol you got assigned if playerX == True: while status == True: number = int(message_pipe.decode('utf-8')) #check if the spot is free if board[number] != "X" and board[number] != "O": status = False yourturn = False print("New status board:") board[number] = "X" showboard() #check for a winning combination if checkall("X") == True: print("You win!") n.whisper(OPPONENT, str(number).encode('utf-8')) break #when there's no winning combination, it's the other player's turn else: print("Waiting for opponent's move...") #let your opponent know which number you chose n.whisper(OPPONENT, str(number).encode('utf-8')) else: print("Spot taken, try again") message_pipe = pipe.recv() else: while status == True: number = int(message_pipe.decode('utf-8')) if board[number] != "X" and board[number] != "O": status = False yourturn = False print("New status board:") board[number] = "O" showboard() if checkall("O") == True: print("You win!") n.whisper(OPPONENT, str(number).encode('utf-8')) break else: print("Waiting for opponent's move...") n.whisper(OPPONENT, str(number).encode('utf-8')) else: print("Spot taken, try again") message_pipe = pipe.recv() elif message_pipe.decode( 'utf-8').isdigit() == True and yourturn == False: print("It's not your turn, wait for your opponent's move") #if the message isn't a number, it is send as a message to your opponent else: print("Sending message to opponent: %s" % message_pipe.decode('utf-8')) n.whisper(OPPONENT, message_pipe) # Received messages from system or messages from other peers else: cmds = n.recv() #print(">>>>>>>RECEIVED MESSAGE: ", cmds) msg_type = cmds.pop(0) player_uuid = uuid.UUID(bytes=cmds.pop(0)) #OPPONENT = player_uuid #print("player uuid: ", player_uuid) msg_name = cmds.pop(0) if msg_type.decode('utf-8') == "ENTER": headers = json.loads(cmds.pop(0).decode('utf-8')) network_players += 1 if network_players == 2: print( "--------------------------------------------------------------------------------" ) print("New player discovered in network") print("Name:", headers.get("header_name")) print( "--------------------------------------------------------------------------------" ) elif msg_type.decode('utf-8') == "JOIN": connected_players += 1 #check if there's stil room for a player if connected_players > 2: leave = "No free spot left" n.whisper(player_uuid, leave.encode('utf-8')) elif connected_players == 2: print( "--------------------------------------------------------------------------------" ) print("%s joined group" % headers.get("header_name"), cmds.pop(0).decode('utf-8')) print( "--------------------------------------------------------------------------------" ) #if there are 2 players, you know your opponent: OPPONENT = player_uuid showboard() #randomly choose if you want to start assign = random.randint(0, 1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) elif msg_type.decode('utf-8') == "WHISPER": message_opponent = cmds.pop(0).decode('utf-8') if message_opponent == "No free spot left": leave_counter += 1 #if you get the message that you must leave from 2 other players, you are the third player if leave_counter == 2: print(message_opponent) break #if the random generators both got a compatible result, the game can start elif message_opponent == "$$Istart" and player_start == False: playerX = False yourturn = False print("You are symbol O") print("You opponent may start, please wait...") elif message_opponent == "$$Ustart" and player_start == True: playerX = True yourturn = True print("You are symbol X") print("You may start") print("Where do you want to place your X?") #when the results are incompatible: try again elif message_opponent == "$$Istart" and player_start == True: assign = random.randint(0, 1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) elif message_opponent == "$$Ustart" and player_start == False: assign = random.randint(0, 1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) #if you receive a number, this is your opponent's move elif message_opponent.isdigit() == True: yourturn = True print( "--------------------------------------------------------------------------------" ) print("Number opponent: ", message_opponent) print("New status board:") #check for a winning combination based on which player you are if playerX == True: board[int(message_opponent)] = "O" showboard() if checkall('O') == True: print("You loose!") break #if your opponent didn't make a winning combination, it's your turn else: print("Your turn") print("Where do you want to place your X?") else: board[int(message_opponent)] = "X" showboard() if checkall('X') == True: print("You loose!") break else: print("Your turn") print("Where do you want to place your O?") #if you just received a message, print it else: print("Opponent says: ", message_opponent) elif msg_type.decode('utf-8') == "EXIT": if connected_players == 2: print("%s left network" % headers.get("header_name")) connected_players -= 1 print("Total connected players: ", connected_players) leave_counter -= 1 print("Game stopped") n.stop()
class Authority(): def __init__(self): self.node = Pyre("GAME_AUTH") self.node.set_header("AUTHORITY", "TRUE") self.node.start() self.node.join("world:position") self.node.join("ctf:teams") self.node.join("ctf:dropflag") self.node.join("ctf:gotflag") self.poller = zmq.Poller() self.poller.register(self.node.socket(), zmq.POLLIN) self.players = AuthorityPlayerManager() self.teams = {"blue": [], "red": []} self.level = SaveLevel('./assets/maps/CAPFLAG MAP NAT') red_spawn_pos = self.level.get_place(Place.RED_SPAWN) blue_spawn_pos = self.level.get_place(Place.BLUE_SPAWN) self.flags = { "blue": { "x": blue_spawn_pos[0], "y": blue_spawn_pos[1], "owner": '', "timer": 0 }, "red": { "x": red_spawn_pos[0], "y": red_spawn_pos[1], "owner": '', "timer": 0 } } self.serve() def set_teams(self): blue_players = self.teams["blue"] red_players = self.teams["red"] # Check for removed players in RED for i, playerUUID in enumerate(red_players): if playerUUID not in self.players.players.keys(): red_players.pop(i) # Check for removed players in BLUE for i, playerUUID in enumerate(blue_players): if playerUUID not in self.players.players.keys(): blue_players.pop(i) # Add new players for playerUUID, player in self.players.players.items(): if not (playerUUID in blue_players or playerUUID in red_players): if len(blue_players) > len(red_players): red_players.append(playerUUID) else: blue_players.append(playerUUID) print("Teams: " + "RED: " + ','.join(red_players) + " | BLUE: " + ','.join(blue_players)) self.node.shout("ctf:teams", bson.dumps(self.teams)) def set_flags(self, flag_info): return def update_flags(self): self.node.shout("ctf:flags", bson.dumps(self.flags)) def get_team_from_uuid(self, uuid): place = None if str(uuid) in self.teams['red']: place = Place.RED_SPAWN elif str(uuid) in self.teams['blue']: place = Place.BLUE_SPAWN return place def serve(self): clock = Clock() while True: clock.tick(60) # check network events = self.get_events() if events: try: for event in events: # Update the teams on JOIN and EXIT if event.type == 'JOIN': if event.group == 'ctf:dropflag': for team, flag in self.flags.items(): if flag['owner'] == '': self.node.shout( 'ctf:dropflag', bson.dumps({ 'x': flag['x'], 'y': flag['y'], 'team': team })) elif event.group == 'ctf:gotflag': for team, flag in self.flags.items(): if flag['owner'] != '': self.node.shout( 'ctf:gotflag', bson.dumps({ 'uuid': flag['owner'], 'team': team })) elif event.group == 'ctf:teams': self.players.set(self.node.peers()) self.set_teams() place = self.get_team_from_uuid( event.peer_uuid) pos = self.level.get_place(place) self.node.whisper( event.peer_uuid, bson.dumps({ 'type': 'teleport', 'x': pos[0], 'y': pos[1] })) elif event.type == 'EXIT': for team, flag in self.flags.items(): if flag['owner'] == str(event.peer_uuid): # flag owner is leaving, drop player = self.players.get(event.peer_uuid) flag['x'] = player.x flag['y'] = player.y flag['owner'] = '' self.node.shout( 'ctf:dropflag', bson.dumps({ 'x': flag['x'], 'y': flag['y'], 'team': team })) self.players.set(self.node.peers()) self.set_teams() elif event.type == 'SHOUT': if event.group == "world:position": new_position = bson.loads(event.msg[0]) network_player = self.players.get( event.peer_uuid) network_player.set_position(new_position) # check if flag has been captured for team, flag in self.flags.items(): if flag['owner'] != str(event.peer_uuid): continue tile = self.level.get_tile( new_position['x'], new_position['y']) if tile == TileType.RED_BLOCK and team == 'blue': # TODO: blue's flag has been captured spawn = Place.BLUE_SPAWN elif tile == TileType.BLUE_BLOCK and team == 'red': # TODO: red's flag has been captured spawn = Place.RED_SPAWN else: continue position = self.level.get_place(spawn) flag['x'] = position[0] flag['y'] = position[1] flag['owner'] = '' self.node.shout( 'ctf:dropflag', bson.dumps({ 'x': flag['x'], 'y': flag['y'], 'team': team })) if event.group == 'ctf:gotflags': flag_info = bson.loads(event.msg[0]) self.set_flags(flag_info) elif event.type == 'WHISPER': msg = bson.loads(event.msg[0]) network_player = self.players.get(event.peer_uuid) if msg['type'] == 'death_report': player = self.players.get(event.peer_uuid) previously_owned_flag = None if self.flags['blue']['owner'] == str( event.peer_uuid): previously_owned_flag = 'blue' elif self.flags['red']['owner'] == str( event.peer_uuid): previously_owned_flag = 'red' if previously_owned_flag: flag = self.flags[previously_owned_flag] flag['owner'] = '' self.node.shout( 'ctf:dropflag', bson.dumps({ 'x': player.x, 'y': player.y, 'team': previously_owned_flag })) place = self.get_team_from_uuid( event.peer_uuid) pos = self.level.get_place(place) self.node.whisper( event.peer_uuid, bson.dumps({ 'type': 'teleport', 'x': pos[0], 'y': pos[1] })) player.x = pos[0] player.y = pos[1] except Exception as e: print(e) import traceback print(traceback.format_exc()) pass for team, flag in self.flags.items(): if flag["owner"] != '': continue for uuid, player in self.players.players.items(): if flag['x'] == player.x and flag['y'] == player.y: team_place = self.get_team_from_uuid(uuid) pos = self.level.get_place(team_place) if team == 'red' and team_place == Place.RED_SPAWN or team == 'blue' and team_place == Place.BLUE_SPAWN: if player.x == pos[0] and player.y == pos[1]: continue self.node.shout( 'ctf:dropflag', bson.dumps({ 'x': pos[0], 'y': pos[1], 'team': team })) else: flag["owner"] = uuid self.node.shout( 'ctf:gotflag', bson.dumps({ 'uuid': uuid, 'team': team })) break def poll(self): return dict(self.poller.poll(0)) def peers(self): return self.node.peers() def stop(self): self.node.stop() def get_events(self): changes = self.poll() if self.node.socket() in changes and changes[ self.node.socket()] == zmq.POLLIN: events = self.node.recent_events() return events
def chat_task(ctx, pipe): print("Game started") print("Name: %s" %NAME) connected_players = 1 network_players = 1 leave_counter = 0 #Set up node for the game n = Pyre("") n.set_header("header_name", NAME) #Join the group n.join(GROUPNAME) #Start broadcasting node n.start() # Set up poller poller = zmq.Poller() poller.register(pipe, zmq.POLLIN) #Local pipe (contains commands/messages we send through terminal) poller.register(n.socket(), zmq.POLLIN) # A while loop constantly polls for new items = PULL system while True: #Wait for new message to be polled. This function blocks until there is a new message items = dict(poller.poll()) #This are messages from ourselves if pipe in items: message_pipe = pipe.recv() if message_pipe.decode('utf-8') == STOP_COMMAND: break #check if the message is a number elif message_pipe.decode('utf-8').isdigit() == True and yourturn == True: #variable to keep the loop going until a correct number is given status = True #check which symbol you got assigned if playerX == True: while status == True: number = int(message_pipe.decode('utf-8')) #check if the spot is free if board[number] != "X" and board[number] != "O": status = False yourturn = False print("New status board:") board[number] = "X" showboard() #check for a winning combination if checkall("X") == True: print("You win!") n.whisper(OPPONENT,str(number).encode('utf-8')) break #when there's no winning combination, it's the other player's turn else: print("Waiting for opponent's move...") #let your opponent know which number you chose n.whisper(OPPONENT,str(number).encode('utf-8')) else: print("Spot taken, try again") message_pipe = pipe.recv() else: while status == True: number = int(message_pipe.decode('utf-8')) if board[number] != "X" and board[number] != "O": status = False yourturn = False print("New status board:") board[number] = "O" showboard() if checkall("O") == True: print("You win!") n.whisper(OPPONENT,str(number).encode('utf-8')) break else: print("Waiting for opponent's move...") n.whisper(OPPONENT,str(number).encode('utf-8')) else: print("Spot taken, try again") message_pipe = pipe.recv() elif message_pipe.decode('utf-8').isdigit() == True and yourturn == False: print("It's not your turn, wait for your opponent's move") #if the message isn't a number, it is send as a message to your opponent else: print("Sending message to opponent: %s" %message_pipe.decode('utf-8')) n.whisper(OPPONENT,message_pipe) # Received messages from system or messages from other peers else: cmds = n.recv() #print(">>>>>>>RECEIVED MESSAGE: ", cmds) msg_type = cmds.pop(0) player_uuid = uuid.UUID(bytes=cmds.pop(0)) #OPPONENT = player_uuid #print("player uuid: ", player_uuid) msg_name = cmds.pop(0) if msg_type.decode('utf-8') == "ENTER": headers = json.loads(cmds.pop(0).decode('utf-8')) network_players += 1 if network_players == 2: print("--------------------------------------------------------------------------------") print("New player discovered in network") print("Name:", headers.get("header_name")) print("--------------------------------------------------------------------------------") elif msg_type.decode('utf-8') == "JOIN": connected_players += 1 #check if there's stil room for a player if connected_players > 2: leave = "No free spot left" n.whisper(player_uuid, leave.encode('utf-8')) elif connected_players == 2: print("--------------------------------------------------------------------------------") print("%s joined group" %headers.get("header_name"), cmds.pop(0).decode('utf-8')) print("--------------------------------------------------------------------------------") #if there are 2 players, you know your opponent: OPPONENT = player_uuid showboard() #randomly choose if you want to start assign = random.randint(0,1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) elif msg_type.decode('utf-8') == "WHISPER": message_opponent = cmds.pop(0).decode('utf-8') if message_opponent == "No free spot left": leave_counter += 1 #if you get the message that you must leave from 2 other players, you are the third player if leave_counter == 2: print(message_opponent) break #if the random generators both got a compatible result, the game can start elif message_opponent == "$$Istart" and player_start == False: playerX = False yourturn = False print("You are symbol O") print("You opponent may start, please wait...") elif message_opponent == "$$Ustart" and player_start == True: playerX = True yourturn = True print("You are symbol X") print("You may start") print("Where do you want to place your X?") #when the results are incompatible: try again elif message_opponent == "$$Istart" and player_start == True: assign = random.randint(0,1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) elif message_opponent == "$$Ustart" and player_start == False: assign = random.randint(0,1) if assign == 1: player_start = True n.whisper(OPPONENT, "$$Istart".encode('utf-8')) else: player_start = False n.whisper(OPPONENT, "$$Ustart".encode('utf-8')) #if you receive a number, this is your opponent's move elif message_opponent.isdigit() == True: yourturn = True print("--------------------------------------------------------------------------------") print("Number opponent: ",message_opponent) print("New status board:") #check for a winning combination based on which player you are if playerX == True: board[int(message_opponent)] = "O" showboard() if checkall('O') == True: print("You loose!") break #if your opponent didn't make a winning combination, it's your turn else: print("Your turn") print("Where do you want to place your X?") else: board[int(message_opponent)] = "X" showboard() if checkall('X') == True: print("You loose!") break else: print("Your turn") print("Where do you want to place your O?") #if you just received a message, print it else: print("Opponent says: ",message_opponent) elif msg_type.decode('utf-8') == "EXIT": if connected_players == 2: print("%s left network" %headers.get("header_name")) connected_players -= 1 print("Total connected players: ", connected_players) leave_counter -= 1 print("Game stopped") n.stop()
data = rec_msg[-1] data = data.decode('utf-8') if str(data) == 'NameRequest': n.shout("CHAT", msg_broadcast_name.encode('utf-8')) if str(msg_type) == 'SHOUT' or str(msg_type) == 'WHISPER': try: jdata = json.loads(data) have_command = True except Exception as e: print('Exception: ', e) if have_command: for item in jdata['payload']['commandList']: if item['command'] == "GOTO": answers['information'] = item['location'] elif item['command'] == "POSE": answers['information'] = "0, 10, 20" elif item['command'] == "RESUME": answers['information'] = "RESUME received" elif item['command'] == "STOP": answers['information'] = "Robot stopped" answers['command'] = "ANSWER" msg_data['payload']['answerList'][0] = answers jmsg_data = json.dumps(msg_data).encode('utf-8') n.whisper(sender_uuid, jmsg_data) print("message sent") print('Finished')
if jdata['payload']['answerList'][0]['command'] == "ANSWER": # send_next_query = True print('received answer:') print(jdata['payload']['answerList']) received_answer = jdata['payload']['answerList'] except Exception as e: # print('Exception: ', e) pass if send_next_query: msg_data['payload']['commandList'][0] = { "command": "GETQUERY", "features": features_list, "start_time": start_query_time, "end_time": end_query_time } jmsg_data = json.dumps(msg_data).encode('utf-8') dest_uuid = nodes_list[dest_name] n.whisper(dest_uuid, jmsg_data) send_next_query = False if get_info: msg_data['payload']['commandList'][0] = {"command": "SENDINFO"} jmsg_data = json.dumps(msg_data).encode('utf-8') dest_uuid = nodes_list[dest_name] n.whisper(dest_uuid, jmsg_data) send_next_query = True get_info = False n.stop() print('Program Finished')
class Bridge(object): """docstring for Bridge""" def __init__(self, uvc_id): super(Bridge, self).__init__() self.data_seq = 0 self.note_seq = 0 # init capture self.cap = uvc.Capture(uvc_id) logger.info('Initialised uvc device %s'%self.cap.name) # init pyre self.network = Pyre(socket.gethostname()+self.cap.name[-4:]) self.network.start() logger.info('Bridging under "%s"'%self.network.name()) # init sensor sockets ctx = zmq.Context() generic_url = 'tcp://*:*' public_ep = self.network.endpoint() self.note, self.note_url = self.bind(ctx, zmq.PUB , generic_url, public_ep) self.data, self.data_url = self.bind(ctx, zmq.PUB , generic_url, public_ep,set_hwm=1) self.cmd , self.cmd_url = self.bind(ctx, zmq.PULL, generic_url, public_ep) def loop(self): logger.info('Entering bridging loop...') self.network.shout('pupil-mobile', self.sensor_attach_json()) try: while True: self.poll_network() self.poll_cmd_socket() self.publish_frame() except KeyboardInterrupt: pass except Exception: import traceback traceback.print_exc() finally: self.network.shout('pupil-mobile', json.dumps({ 'subject' : 'detach', 'sensor_uuid': self.network.uuid().hex })) logger.info('Leaving bridging loop...') def publish_frame(self): frame = self.cap.get_frame_robust() now = int(time.time()*1000000) index = self.data_seq self.data_seq += 1 self.data_seq %= sequence_limit jpeg_buffer = frame.jpeg_buffer meta_data = struct.pack('<LLLLQLL', 0x10, frame.width, frame.height, index, now, jpeg_buffer.size, 0) self.data.send_multipart([self.network.uuid().hex, meta_data, jpeg_buffer]) def poll_network(self): while has_data(self.network.socket()): event = PyreEvent(self.network) if event.type == 'JOIN' and event.group == 'pupil-mobile': self.network.whisper(event.peer_uuid, self.sensor_attach_json()) def poll_cmd_socket(self): while has_data(self.cmd): sensor, cmd_str = self.cmd.recv_multipart() try: cmd = json.loads(cmd_str) except Exception as e: logger.debug('Could not parse received cmd: %s'%cmd_str) else: logger.debug('Received cmd: %s'%cmd) if cmd.get('action') == 'refresh_controls': self.publish_controls() elif cmd.get('action') == 'set_control_value': val = cmd.get('value', 0) if cmd.get('control_id') == 'CAM_RATE': self.cap.frame_rate = self.cap.frame_rates[val] elif cmd.get('control_id') == 'CAM_RES': self.cap.frame_size = self.cap.frame_sizes[val] self.publish_controls() def __del__(self): self.note.close() self.data.close() self.cmd.close() self.network.stop() def publish_controls(self): self.note.send_multipart([ self.network.uuid().hex, self.frame_size_control_json()]) self.note.send_multipart([ self.network.uuid().hex, self.frame_rate_control_json()]) def sensor_attach_json(self): sensor = { "subject" : "attach", "sensor_name" : self.cap.name, "sensor_uuid" : self.network.uuid().hex, "sensor_type" : 'video', "notify_endpoint" : self.note_url, "command_endpoint": self.cmd_url, "data_endpoint" : self.data_url } return json.dumps(sensor) def frame_size_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fs = self.cap.frame_sizes.index(self.cap.frame_size) return json.dumps({ "subject" : "update", "control_id" : "CAM_RES", "seq" : index, "changes" : { "value" : curr_fs, "dtype" : 'intmapping', "min" : None, "max" : None, "res" : None, "def" : 0, "caption" : 'Resolution', "readonly" : False, "map" : [{ 'value' : idx, 'caption': '%ix%i'%fs } for idx,fs in enumerate(self.cap.frame_sizes)] } }) def frame_rate_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fr = self.cap.frame_rates.index(self.cap.frame_rate) return json.dumps({ "subject" : "update", "control_id" : "CAM_RATE", "seq" : index, "changes" : { "value" : curr_fr, "dtype" : 'intmapping', "min" : None, "max" : None, "res" : None, "def" : 0, "caption" : 'Frame Rate', "readonly" : False, "map" : [{ 'value' : idx, 'caption': '%.1f Hz'%fr } for idx,fr in enumerate(self.cap.frame_rates)] } }) def bind(self, ctx, sock_type, url, public_ep, set_hwm=None): sock = ctx.socket(sock_type) if set_hwm: sock.set_hwm(set_hwm) sock.bind(url) ep = sock.last_endpoint port = ep.split(':')[-1] public_ep.split(':')[-1] public_addr = public_ep.split(':')[:-1] return sock, ':'.join(public_addr+[port])
def chat_task(ctx,pipe): print("communication started") GROUPNAME = "Quizzzzz" StopCmnd = "$$quit" OPPONENT = "opponent" print("name: %s" %NAME) connected_players = 1 # set up node for the user n = Pyre(GROUPNAME) n.set_header('Name', NAME) # join the groupchat n.join(GROUPNAME) #print("UUID %s" %n.uuid()) # start broadcasting signal n.start() # set up poller poller = zmq.Poller() poller.register(pipe,zmq.POLLIN) poller.register(n.socket(),zmq.POLLIN) # looping constantly to recieve messages while True: items = dict(poller.poll()) if pipe in items: message = pipe.recv() if message.decode('utf-8') == StopCmnd: break # uppercase letters for question to whole group elif message.decode('utf-8').isupper() == True: print("Question is: %s" %message) n.shouts(GROUPNAME,"Question to group is: %s" %message.decode('utf-8')) answer = 0 # lowercase to last person who asked question in the group elif message.decode('utf-8').islower() == True: message = NAME + "'s answer is=" + message n.whisper(PEER,message) else: print("please don't mix up or lowercase or use not only numbers") else: msgrecv = n.recv() #print(msgrecv) msg_type = msgrecv.pop(0) msg_sender = uuid.UUID(bytes=msgrecv.pop(0)) PEER = msg_sender msg_name = msgrecv.pop(0) if msg_type.decode('utf-8') == "ENTER": headers = json.loads(msgrecv.pop(0).decode('utf-8')) print("New player discovered in network") print("New player = %s " %headers.get("Name")) elif msg_type.decode('utf-8') == "JOIN": print("New player has joined the group") print("New player = %s" %headers.get("Name")) connected_players += 1 print("#players = %s" %connected_players) elif msg_type.decode('utf-8') == "SHOUT": print(msgrecv.pop(1)) elif msg_type.decode('utf-8') == "WHISPER": if msgrecv[0] == "You have to ask next question": print("You have to ask next question") n.shout(GROUPNAME, "%s is new quizmaster" %NAME) answer = 0 else: print(msgrecv.pop(0)) answer +=1 if answer == connected_players -1: #choosing new quizmaster randomly players = n.peers() next_master = players.pop(random.randint(0,connected_players-2)) n.whisper(next_master,"You have to ask next question") print("Left current game") n.stop()
class Bridge(object): """docstring for Bridge""" def __init__(self, uvc_id): super(Bridge, self).__init__() self.data_seq = 0 self.note_seq = 0 # init capture self.cap = uvc.Capture(uvc_id) logger.info('Initialised uvc device {}'.format(self.cap.name)) # init pyre self.network = Pyre(socket.gethostname()+self.cap.name[-4:]) self.network.join(GROUP) self.network.start() logger.info('Bridging under "{}"'.format(self.network.name())) # init sensor sockets ctx = zmq.Context() generic_url = 'tcp://*:*' public_ep = self.network.endpoint() self.note, self.note_url = self.bind(ctx, zmq.PUB, generic_url, public_ep) self.data, self.data_url = self.bind(ctx, zmq.PUB, generic_url, public_ep, set_hwm=1) self.cmd, self.cmd_url = self.bind(ctx, zmq.PULL, generic_url, public_ep) def loop(self): logger.info('Entering bridging loop...') self.network.shout(GROUP, self.sensor_attach_json().encode()) try: while True: self.poll_network() self.poll_cmd_socket() self.publish_frame() except KeyboardInterrupt: pass except Exception: import traceback traceback.print_exc() finally: self.network.shout(GROUP, json.dumps({ 'subject': 'detach', 'sensor_uuid': self.network.uuid().hex }).encode()) logger.info('Leaving bridging loop...') def publish_frame(self): frame = self.cap.get_frame_robust() now = time.time() index = self.data_seq self.data_seq += 1 self.data_seq %= sequence_limit jpeg_buffer = frame.jpeg_buffer m = hashlib.md5(jpeg_buffer) lower_end = int(m.hexdigest(), 16) % 0x100000000 meta_data = struct.pack('<LLLLdLL', 0x10, frame.width, frame.height, index, now, jpeg_buffer.size, lower_end) self.data.send_multipart([self.network.uuid().hex.encode(), meta_data, jpeg_buffer]) def poll_network(self): for event in self.network.recent_events(): if event.type == 'JOIN' and event.group == GROUP: self.network.whisper(event.peer_uuid, self.sensor_attach_json().encode()) def poll_cmd_socket(self): while has_data(self.cmd): sensor, cmd_str = self.cmd.recv_multipart() try: cmd = json.loads(cmd_str.decode()) except Exception as e: logger.debug('Could not parse received cmd: {}'.format(cmd_str)) else: logger.debug('Received cmd: {}'.format(cmd)) if cmd.get('action') == 'refresh_controls': self.publish_controls() elif cmd.get('action') == 'set_control_value': val = cmd.get('value', 0) if cmd.get('control_id') == 'CAM_RATE': self.cap.frame_rate = self.cap.frame_rates[val] elif cmd.get('control_id') == 'CAM_RES': self.cap.frame_size = self.cap.frame_sizes[val] self.publish_controls() def __del__(self): self.note.close() self.data.close() self.cmd.close() self.network.stop() def publish_controls(self): self.note.send_multipart([ self.network.uuid().hex.encode(), self.frame_size_control_json().encode()]) self.note.send_multipart([ self.network.uuid().hex.encode(), self.frame_rate_control_json().encode()]) def sensor_attach_json(self): sensor = { "subject": "attach", "sensor_name": self.cap.name, "sensor_uuid": self.network.uuid().hex, "sensor_type": 'video', "notify_endpoint": self.note_url, "command_endpoint": self.cmd_url, "data_endpoint": self.data_url } return json.dumps(sensor) def frame_size_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fs = self.cap.frame_sizes.index(self.cap.frame_size) return json.dumps({ "subject": "update", "control_id": "CAM_RES", "seq": index, "changes": { "value": curr_fs, "dtype": 'intmapping', "min": None, "max": None, "res": None, "def": 0, "caption": 'Resolution', "readonly": False, "map": [{ 'value': idx, 'caption': '{:d}x{:d}'.format(*fs) } for idx, fs in enumerate(self.cap.frame_sizes)] } }) def frame_rate_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fr = self.cap.frame_rates.index(self.cap.frame_rate) return json.dumps({ "subject": "update", "control_id": "CAM_RATE", "seq": index, "changes": { "value": curr_fr, "dtype": 'intmapping', "min": None, "max": None, "res": None, "def": 0, "caption": 'Frame Rate', "readonly": False, "map": [{ 'value': idx, 'caption': '{:.1f} Hz'.format(fr) } for idx, fr in enumerate(self.cap.frame_rates)] } }) def bind(self, ctx, sock_type, url, public_ep, set_hwm=None): sock = ctx.socket(sock_type) if set_hwm: sock.set_hwm(set_hwm) sock.bind(url) ep = sock.last_endpoint.decode() port = ep.split(':')[-1] public_ep.split(':')[-1] public_addr = public_ep.split(':')[:-1] return sock, ':'.join(public_addr+[port])
class Bridge(object): """docstring for Bridge""" def __init__(self, uvc_id): super(Bridge, self).__init__() self.data_seq = 0 self.note_seq = 0 # init capture self.cap = uvc.Capture(uvc_id) logger.info("Initialised uvc device {}".format(self.cap.name)) # init pyre self.network = Pyre(socket.gethostname() + self.cap.name[-4:]) self.network.join(GROUP) self.network.start() logger.info('Bridging under "{}"'.format(self.network.name())) # init sensor sockets ctx = zmq.Context() generic_url = "tcp://*:*" public_ep = self.network.endpoint() self.note, self.note_url = self.bind(ctx, zmq.PUB, generic_url, public_ep) self.data, self.data_url = self.bind(ctx, zmq.PUB, generic_url, public_ep, set_hwm=1) self.cmd, self.cmd_url = self.bind(ctx, zmq.PULL, generic_url, public_ep) def loop(self): logger.info("Entering bridging loop...") self.network.shout(GROUP, self.sensor_attach_json().encode()) try: while True: self.poll_network() self.poll_cmd_socket() self.publish_frame() except KeyboardInterrupt: pass except Exception: import traceback traceback.print_exc() finally: self.network.shout( GROUP, json.dumps({ "subject": "detach", "sensor_uuid": self.network.uuid().hex }).encode(), ) logger.info("Leaving bridging loop...") def publish_frame(self): frame = self.cap.get_frame_robust() now = time.time() index = self.data_seq self.data_seq += 1 self.data_seq %= sequence_limit jpeg_buffer = frame.jpeg_buffer m = hashlib.md5(jpeg_buffer) lower_end = int(m.hexdigest(), 16) % 0x100000000 meta_data = struct.pack( "<LLLLdLL", 0x10, frame.width, frame.height, index, now, jpeg_buffer.size, lower_end, ) self.data.send_multipart( [self.network.uuid().hex.encode(), meta_data, jpeg_buffer]) def poll_network(self): for event in self.network.recent_events(): if event.type == "JOIN" and event.group == GROUP: self.network.whisper(event.peer_uuid, self.sensor_attach_json().encode()) def poll_cmd_socket(self): while has_data(self.cmd): sensor, cmd_str = self.cmd.recv_multipart() try: cmd = json.loads(cmd_str.decode()) except Exception as e: logger.debug( "Could not parse received cmd: {}".format(cmd_str)) else: logger.debug("Received cmd: {}".format(cmd)) if cmd.get("action") == "refresh_controls": self.publish_controls() elif cmd.get("action") == "set_control_value": val = cmd.get("value", 0) if cmd.get("control_id") == "CAM_RATE": self.cap.frame_rate = self.cap.frame_rates[val] elif cmd.get("control_id") == "CAM_RES": self.cap.frame_size = self.cap.frame_sizes[val] self.publish_controls() def __del__(self): self.note.close() self.data.close() self.cmd.close() self.network.stop() def publish_controls(self): self.note.send_multipart([ self.network.uuid().hex.encode(), self.frame_size_control_json().encode() ]) self.note.send_multipart([ self.network.uuid().hex.encode(), self.frame_rate_control_json().encode() ]) def sensor_attach_json(self): sensor = { "subject": "attach", "sensor_name": self.cap.name, "sensor_uuid": self.network.uuid().hex, "sensor_type": "video", "notify_endpoint": self.note_url, "command_endpoint": self.cmd_url, "data_endpoint": self.data_url, } return json.dumps(sensor) def frame_size_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fs = self.cap.frame_sizes.index(self.cap.frame_size) return json.dumps({ "subject": "update", "control_id": "CAM_RES", "seq": index, "changes": { "value": curr_fs, "dtype": "intmapping", "min": None, "max": None, "res": None, "def": 0, "caption": "Resolution", "readonly": False, "map": [{ "value": idx, "caption": "{:d}x{:d}".format(*fs) } for idx, fs in enumerate(self.cap.frame_sizes)], }, }) def frame_rate_control_json(self): index = self.note_seq self.note_seq += 1 self.note_seq %= sequence_limit curr_fr = self.cap.frame_rates.index(self.cap.frame_rate) return json.dumps({ "subject": "update", "control_id": "CAM_RATE", "seq": index, "changes": { "value": curr_fr, "dtype": "intmapping", "min": None, "max": None, "res": None, "def": 0, "caption": "Frame Rate", "readonly": False, "map": [{ "value": idx, "caption": "{:.1f} Hz".format(fr) } for idx, fr in enumerate(self.cap.frame_rates)], }, }) def bind(self, ctx, sock_type, url, public_ep, set_hwm=None): sock = ctx.socket(sock_type) if set_hwm: sock.set_hwm(set_hwm) sock.bind(url) ep = sock.last_endpoint.decode() port = ep.split(":")[-1] public_ep.split(":")[-1] public_addr = public_ep.split(":")[:-1] return sock, ":".join(public_addr + [port])
def network_manager(self, ctx, write_pipe, node_name, overlay_network_name, read_pipe): # create the poller to wait for messages from pipes and network poller = zmq.Poller() poller.register(write_pipe, zmq.POLLIN) # create the Pyre node object node = Pyre(node_name + str(uuid.uuid4())) # register node to the network, start it and register for events with # the poller. node.join(overlay_network_name) node.start() poller.register(node.socket(), zmq.POLLIN) while (True): # do stuff, aka wait and decode messages items = dict(poller.poll()) if write_pipe in items and items[write_pipe] == zmq.POLLIN: # here is where the thread receives internal data # check if we have to send something outside # or eventually die gracefully message = write_pipe.recv() # here I have a Command + a FardNetworkData object decoded_message = pickle.loads(message) command = decoded_message[0] network_data = decoded_message[1] if command == "$$STOP": # message to quit here break elif command == "$$GET_PEERS": # only synchronous command, retrieves the peers inside the # network of tasks. group = network_data.group peers = node.peers_by_group(group) list_of_peers = [] for peer in peers: list_of_peers.append(str(peer)) write_pipe.send(pickle.dumps(str(";".join(list_of_peers)))) elif command == "$$SEND_MESSAGE" in decoded_message: # send message to a single peer using Pyre # if requested, send back the message to the same node that # sent it. peer = network_data.peer network_data.sender_peer = str(node.uuid()) network_data.message_type = "peer" node.whisper(uuid.UUID(peer), pickle.dumps(network_data)) if network_data.auto_send and peer == network_data.sender_peer: read_pipe.send(pickle.dumps(network_data)) elif command == "$$SEND_TASK_MESSAGE": # send message to a group of identical tasks using Pyre. # Currently implemented with a shout that is ignored by a # receiver if the task name is different from his. # if requested, send back the message to the same node that # sent it. network_data.sender_peer = str(node.uuid()) network_data.message_type = "task" node.shout(group, pickle.dumps(network_data)) if network_data.auto_send: read_pipe.send(pickle.dumps(network_data)) elif command == "$$SEND_GROUP_MESSAGE": # send message to the whole application using Pyre # if requested, send back the message to the same node that # sent it. group = network_data.group network_data.sender_peer = str(node.uuid()) network_data.message_type = "group" node.shout(group, pickle.dumps(network_data)) if network_data.auto_send: read_pipe.send(pickle.dumps(network_data)) else: # here is where the thread receives data from the outside # decode messages and reroute them accordingly cmds = node.recv() msg_type = cmds.pop(0).decode('utf-8') peer_uuid = uuid.UUID(bytes=cmds.pop(0)) sender_node_name = cmds.pop(0).decode('utf-8') if msg_type == "SHOUT": group = cmds.pop(0).decode('utf-8') read_pipe.send(cmds.pop(0)) elif msg_type == "WHISPER": read_pipe.send(cmds.pop(0)) # elif msg_type == "ENTER": # headers = json.loads(cmds.pop(0).decode('utf-8')) # print("NODE_MSG HEADERS: %s" % headers) # for key in headers: # print("key = {0}, value = {1}".format(key, headers[key])) # print("NODE_MSG CONT: %s" % cmds) node.stop()
class Agent: """ A class object that represents each app in the network""" def __init__(self, name, ctx, group_name, cpu_clock_rate, experiment_name): self.lock = threading.Lock() self.cpu_clock_rate = cpu_clock_rate self.cpu_load = random.random() self.group_name = group_name self.routing_table = None self.name = name + str(os.getpid()) self.tasks = Queue(-1) self.results = Queue(-1) self.exp_name = experiment_name self.task_duration_no_context = random.random() # compute duration using cpu load, etc self.task_duration_with_context = random.random() #self.weights = 'rnn-model-attention-weights.h5' #self.model = rnn_model() # self.model._make_predict_function() # self.model.load_weights(self.weights) self.agent = Pyre( name=self.name, ctx=ctx or zmq.Context.instance()) try: self.agent.join(group_name) self.agent.start() except Exception as err: logger.error(f'>>> Cant start node: {err}', exc_info=True) def routing_table_setter(self, table): self.lock.acquire() try: # create an ascending round robin routing principle self.routing_table = cycle( sorted(table.items(), key=lambda x: x[1])) finally: self.lock.release() def add_task(self): """populates the task queue with new data for inference""" logger.debug(f'>>> {threading.current_thread().name} started') self.data = cycle(load_data(self.exp_name, 0)) count = 0 while count < 100: task_dict = dict.fromkeys( ['input', 'target', 'task-type', 'task-uuid', 'task-owner-name', 'result', 'duration'], 0) try: input_data, target_data = next(self.data) task_dict['input'] = input_data task_dict['target'] = target_data task_dict['task-type'] = 1 task_dict['task-uuid'] = self.agent.uuid() task_dict['task-owner-name'] = self.agent.name() task_dict['duration'] = time.time() self.tasks.put(task_dict) count += 1 except Exception as err: logger.error(f'>>> Exception type: {err}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop() # Vary the frequency of input tasks time.sleep(random.randint(1, 8)) def vary_cpu_load(self): logger.debug( f'>>> {threading.current_thread().name} thread started') while True: try: self.lock.acquire() self.cpu_load = random.random() self.lock.release() self.compute_duration_with_context() except Exception as err: logger.error(f'>>> Exception: {err}', exc_info=True) time.sleep(random.randint(10, 40)) def compute_duration_with_context(self): try: self.lock.acquire() cpu_load = self.cpu_load task_duration_no_context = self.task_duration_no_context self.task_duration_with_context = ( 1 / task_duration_no_context) / (cpu_load * self.cpu_clock_rate) self.lock.release() except Exception as identifier: logger.error(f'>>> Exception: {identifier}') def compute_local(self, task): """argument is task""" try: task = task task_data = task['input'] target = task['target'] uuid = task['task-uuid'] #predictions = self.model.predict(task_data, verbose=0) #predictions = predictions.flatten() # flatten the target average = mean(task_data.flatten()) # window = 5 # errors = self.regression_error(predictions, target, window) # mu, variance = np.mean(errors), np.var(errors) # probabilities = self.chebyshev_probability(mu, variance, errors) task['task-type'] = task['task-type'] + 1 if uuid == self.agent.uuid(): # put results in our queue if its our uuid self.results.put(average) self.lock.acquire() self.task_duration_no_context = time.time() - task['duration'] self.lock.release() self.compute_duration_with_context() else: task['result'] = average data_byte = pickle.dumps(task, -1) self.agent.whisper(uuid, data_byte) logger.error( f'>>> Results sent back to task owner peer: {task["task-owner-name"]}') except Exception as identifier: logger.error(f'>>> Exception type: {identifier}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop() # clean up if there are issues. def check_results(self): logger.error(f'>>> {threading.current_thread().name} thread started') while True: try: if not self.results.empty(): result = self.results.get() if result <= 0.25: logger.error( f'>>> Critical anomaly detected: {result}') elif result > 0.25 and result < 0.5: logger.error( f'>>> Severe anomaly detected: {result}') elif result > 0.5 and result < 0.75: logger.error( f'>>> Serious anomaly detected: {result}') else: logger.error(f'>>> Mild anomaly detected: {result}') except Exception as err: logger.error(f'>>> Exception: {err}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop() def outbox(self, task, peer_uuid): try: task = pickle.dumps(task, -1) self.agent.whisper(peer_uuid, task) except Exception as identifier: logger.error(f'>>> Exception: {identifier}',exc_info=True) self.agent.leave(self.group_name) self.agent.stop() def num_of_peers(self, table): seen = [] for peer in table: if peer[0] in seen: return len(seen) else: seen.append(peer[0]) def handle_task(self): # decide if to compute locally or offload logger.error(f'>>> {threading.current_thread().name} thread started') while True: try: if not self.tasks.empty(): task = self.tasks.get() self.lock.acquire() local_duration = self.task_duration_with_context table = self.routing_table if table: peer = next(table) # peer = (uuid, latency) if peer[1] < local_duration: self.outbox(task, peer[0]) logger.debug(f'>>> Task offloaded') else: num_of_peers = self.num_of_peers(table) peer = self.search_table( table, num_of_peers, local_duration) if peer: self.lock.release() self.outbox(task, peer[0]) logger.debug(f'>>> Task offloaded') else: self.compute_local(task) logger.debug(f'>>> Task computed locally') else: self.compute_local(task) logger.debug(f'>>> Task computed locally') except Exception as identifier: logger.error( f'>>> Exception type : {identifier}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop() # stop if there are issues time.sleep(random.randint(0, 3)) def search_table(self, table, num_of_peers, local_dur): for id in range(num_of_peers): peer = next(table) if peer[1] < local_dur: return peer else: return None def inbox(self): logger.error(f'>>> {threading.current_thread().name} thread started') try: events = self.agent.events() # works like charm while True: if events: event = next(events) logger.error(f'>>> MSG TYPE: {event.type}') logger.error(f'>>> Sender Agent Name: {event.peer_name}') if event.type == 'WHISPER': msg = pickle.loads(event.msg[0]) if msg['task-type'] == 2: result = msg['result'] self.results.put(result) elif msg['task-type'] == 1: # peer sent us a task to execute self.tasks.put(msg) elif event.type == 'SHOUT': # message from the Access Point AP msg = pickle.loads(event.msg[0]) if msg['msg-type'] == 'REQUEST': msg['uuid'] = self.agent.uuid() self.lock.acquire() msg['processing-time'] = self.task_duration_with_context self.lock.release() msg_b = pickle.dumps(msg, -1) self.agent.whisper(event.peer_uuid, msg_b) elif msg['msg-type'] == 'UPDATE': table = msg['table'] own_uuid = self.agent.uuid() if own_uuid in table.keys(): # remove our own UUID to avoid offloading to ourselves del table[own_uuid] self.routing_table_setter(table) except Exception as identifier: logger.error(f'>>> Exception type: {identifier}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop() # leave the cluster if you have issues # compute the chebyshev probability def chebyshev_probability(self, average, varianse, error_val): probability = [] for val in error_val: if val - average >= 1: prob = varianse / ((val - average)**2) probability.append(prob) return probability def regression_error(self, outcome, truth, window): n_data = len(truth) count = 0 errors = [] while count + window <= n_data: error = [abs(y_pred - y_truth) for y_pred, y_truth in zip( outcome[count:count + window], truth[count:count + window])] errors.append(np.mean(error)) count += window return errors def run(self): # start the threads here t1 = threading.Thread(target=self.add_task, name='add task') t2 = threading.Thread(target=self.vary_cpu_load, name='vary cpu load') t3 = threading.Thread(target=self.check_results, name='check results') t4 = threading.Thread(target=self.handle_task, name='handle task') t5 = threading.Thread(target=self.inbox, name='inbox') threads = [t1, t2, t3, t4, t5] try: for thread in threads: thread.start() except Exception as err: logger.error(f'>>> Exception: {err}', exc_info=True) self.agent.leave(self.group_name) self.agent.stop()