示例#1
0
    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)
示例#2
0
文件: chat.py 项目: Rio/pyre
def chat_task(ctx, pipe):
    n = Pyre(ctx)
    n.join("CHAT")
    n.start()

    poller = zmq.Poller()
    poller.register(pipe, zmq.POLLIN)
    poller.register(n.inbox, zmq.POLLIN)
    while(True):
        items = dict(poller.poll())
        if pipe in items and items[pipe] == zmq.POLLIN:
            message = pipe.recv()
            # message to quit
            if message.decode('utf-8') == "$$STOP":
                break
            print("CHAT_TASK: %s" % message)
            n.shout("CHAT", message)
        if n.inbox in items and items[n.inbox] == zmq.POLLIN:
            cmds = n.recv()
            type = cmds.pop(0)
            print("NODE_MSG TYPE: %s" % type)
            print("NODE_MSG PEER: %s" % uuid.UUID(bytes=cmds.pop(0)))
            print("NODE_MSG NAME: %s" % cmds.pop(0))
            if type.decode('utf-8') == "SHOUT":
                print("NODE_MSG GROUP: %s" % cmds.pop(0))
            print("NODE_MSG CONT: %s" % cmds)
    n.stop()
def run_time_sync_master(group):

    pts_group = group + '-time_sync-v1'
  
    # the time source in the example is python time.time you can change this.
    # replace with an implementation that give your custom time in floating sec.
    clock_service = Clock_Sync_Master(time)

    # This example is a clock service only, not a clock follower.
    # Therefore the rank is designed to always trump all others.
    rank = 1000
    discovery = Pyre('pupil-helper-service')
    discovery.join(pts_group)
    discovery.start()
    logger.info('Joining "{}" group with rank {}'.format(pts_group, rank))

    def announce_clock_service_info():
        discovery.shout(pts_group, [repr(rank).encode(), repr(clock_service.port).encode()])

    try:
        for event in discovery.events():
            if event.type == 'JOIN' and event.group == pts_group:
                logger.info('"{}" joined "{}" group. Announcing service.'.format(event.peer_name, pts_group))
                announce_clock_service_info()
    except KeyboardInterrupt:
        pass
    finally:
        logger.info('Leaving "{}" group'.format(pts_group))
        discovery.leave(pts_group)
        discovery.stop()
        clock_service.stop()
示例#4
0
 def open(self) -> None:
     """Create a new pyre instance and join untangled."""
     self.node = Pyre()
     self.node.start()
     self.node.join('untangled2018')
     # used to get our messages
     self.poller = zmq.Poller()
     self.poller.register(self.node.socket(), zmq.POLLIN)
示例#5
0
    def __init__(self):
        self.node = Pyre("GAME_NODE")
        self.node.set_header("HELLO", "ABC")
        self.node.start()
        self.node.join("world:position")
        self.node.join("world:combat")

        self.poller = zmq.Poller()
        self.poller.register(self.node.socket(), zmq.POLLIN)
示例#6
0
文件: network.py 项目: vedb/pyndsi
 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 _thread_loop(self,context,pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(n.socket(), zmq.POLLIN)

        front,back = zhelper.zcreate_pipe(context)
        poller.register(back, zmq.POLLIN)
        def wake_up():
            #on app close this timer calls a closed socket. We simply catch it here.
            try:
                front.send('wake_up')
            except Exception as e:
                logger.debug('Orphaned timer thread raised error: %s'%e)

        if self._time_grandmaster:
            t = Timer(0.1, wake_up)
        else:
            t = Timer(self.time_sync_announce_interval, wake_up)
        t.daemon = True
        t.start()

        while(True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll())
            except zmq.ZMQError:
                logger.warning('Socket fail.')
                continue

            if back in items and items[back] == zmq.POLLIN:
                self._handle_wake_up(back,n,wake_up)


            if pipe in items and items[pipe] == zmq.POLLIN:
                if self._handle_internal(pipe,n):
                    break

            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                self._handle_network(n)
            else:
                pass

        logger.debug('_thread_loop closing.')

        self.thread_pipe = None
        n.stop()
示例#8
0
    def __init__(self):
        self.node = Pyre("GAME_NODE")
        self.node.set_header("AUTHORITY", "FALSE")
        self.node.set_header("NAME", "")
        self.node.start()
        self.node.join("world:position")
        self.node.join("world:combat")
        self.node.join("ctf:teams")
        self.node.join("ctf:dropflag")
        self.node.join("ctf:gotflag")
        self.node.join("players:whois")
        self.node.join("player:name")

        self.poller = zmq.Poller()
        self.poller.register(self.node.socket(), zmq.POLLIN)
    def discovery_task(self, ctx, pipe):
        self.log.debug("Pyre on iface : {}".format(self.iface))

        n = Pyre(self.groupName, sel_iface=self.iface)
        n.set_header("DISCOVERY_Header1","DISCOVERY_HEADER")
        n.join(self.groupName)
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(n.inbox, zmq.POLLIN)

        while(True):
            items = dict(poller.poll())

            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == "$$STOP":
                    break

            if n.inbox in items and items[n.inbox] == zmq.POLLIN:
                cmds = n.recv()
                #self.log.error("NODE_MSG CONT:{}".format(cmds))

                msg_type = cmds.pop(0)
                peer_uuid_bytes = cmds.pop(0)
                peer_uuid = uuid.UUID(bytes=peer_uuid_bytes)

                #self.log.debug("NODE_MSG TYPE: {}".format(msg_type))
                #self.log.debug("NODE_MSG PEER: {}".format(peer_uuid))

                if msg_type.decode('utf-8') == "SHOUT":
                    group_name = cmds.pop(0)
                    #self.log.debug("NODE_MSG GROUP: {}".format(group_name))

                    group_name_2 = cmds.pop(0)
                    #self.log.debug("NODE_MSG GROUP_2: {}".format(group_name_2))

                    discoveryMsg = cmds.pop(0)
                    #self.log.debug("Discovery Msg : {}".format(discoveryMsg))

                    controller = json.loads(discoveryMsg.decode('utf-8'))
                    self.controller_dl = str(controller["downlink"])
                    self.controller_ul = str(controller["uplink"])
                    self.log.info("Discovered Controller DL-{}, UL-{}".format(self.controller_dl, self.controller_ul))

        n.stop()
示例#10
0
    def restart_discovery(self, name):

        if self.discovery:
            if self.discovery.name() == name:
                return
            else:
                self.discovery.leave(self.sync_group)
                self.discovery.stop()
                self.leaderboard = []

        self.node_name = name or gethostname()
        self.discovery = Pyre(self.node_name)
        # Either joining network for the first time or rejoining the same group.
        self.discovery.join(self.sync_group)
        self.discovery.start()
        self.announce_clock_master_info()
示例#11
0
    def indicators_create(self, data, **kwargs):
        if isinstance(data, dict):
            data = Indicator(**data)

        if isinstance(data, Indicator):
            data = [data]

        n = Pyre()

        n.join(CHAN)
        n.start()
        sleep(1)

        for i in data:
            n.shouts(CHAN, str(i))

        n.stop()
示例#12
0
    def __init__(self, name, state: State, node: Pyre, log=None, messageBoard=None):
        if log == None:
            log = []
        if messageBoard == None:
            messageBoard = MemoryBoard()

        super().__init__(node.uuid().hex, state, log, messageBoard, [])
        self._node = node
        self._human_name = name
示例#13
0
        def setup_group_member():
            group_member = Pyre(self.name)
            # set headers
            for header in self.default_headers:
                group_member.set_header(*header)
            # join active group
            group_member.join(self.active_group)

            # start group_member
            group_member.start()
            return group_member
示例#14
0
    def __init__(self, my_name, my_ip, group_name):

        self.name = my_name
        self.ip = my_ip
        self.group = group_name

        # node dict is of the format ip: name
        # This is because a user (name) may move to a new ip.
        # Duplicate ip's are not allowed, but more than 1 ip may share the 
        # same name. This is because a user may log in to multiple devices.
        # 
 
        self.node_dict = {}

        self.node = Pyre(self.group)
        self.node.set_header(self.name, self.ip)
        self.node.join(self.group)
        self.node.start()

        # this runs forever for testing, but should be run as a thread
        self._node_update_task()
示例#15
0
    def __init__(self, myname, port=None, prefix=None):
        # NOTE: Seems to be a bug in Pyre where you can't set the port.
        if port is not None:
            raise NotImplementedError(
                'There is a bug in Pyre that prevents setting of the discovery port. If you require multiple federations of Pyre components, use prefix instead of port in Transport constructor.'
            )

        # dict of remote name to callback. See subscribe method above.
        self._subscribers = {}

        # Callback for all message (or None if none registered)
        self._subscribe_all = None

        self._prefix = prefix

        # Attach the federation name as a prefix to both this channel
        # and the global channel. The global channel is currently
        # just used for QUIT messages.

        if prefix is not None:
            myname = prefix + myname
            self._globalchannel = prefix + "GLOBAL"
        else:
            self._globalchannel = "GLOBAL"

        self._pyre = Pyre(myname)
        if port is not None:
            self._pyre.set_port(port)

        self._pyre.join(myname)
        self._pyre.join(self._globalchannel)
        self._pyre.start()

        # Dict of (UUIDs => IP addresses) that have sent a valid ENTER message
        self._uuid2ip = {}

        self._run = True

        self._readthread = threading.Thread(target=self._readworker)
        self._readthread.start()
示例#16
0
        def setup_group_member():
            group_member = Pyre(self.name)
            # set headers
            for header in self.default_headers:
                group_member.set_header(*header)
            # join active group
            group_member.join(self.active_group)

            # start group_member
            group_member.start()
            return group_member
示例#17
0
def peer(rolename, partnum):
    peername = "%s-%02d" % (rolename, partnum)
    portnum = 5670 + partnum  # fixme: risking collission!
    print(peername)
    ret = Pyre(peername)
    ret.set_port(bytes(str(portnum).encode("ascii")))
    ret.set_header("role", rolename)
    return ret
示例#18
0
    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.node.join("ctf:scores")
        self.node.join("ctf:status")

        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": '',
            },
            "red": {
                "x": red_spawn_pos[0],
                "y": red_spawn_pos[1],
                "owner": '',
            }
        }

        self.scores = {"red": 0, "blue": 0}

        self.serve()
示例#19
0
 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)
示例#20
0
    def restart_discovery(self, name):

        if self.discovery:
            if self.discovery.name() == name:
                return
            else:
                self.discovery.leave(self.sync_group)
                self.discovery.stop()
                self.leaderboard = []

        self.node_name = name or gethostname()
        self.discovery = Pyre(self.node_name)
        # Either joining network for the first time or rejoining the same group.
        self.discovery.join(self.sync_group)
        self.discovery.start()
        self.announce_clock_master_info()
    def __init__(self, myname, port=None, prefix=None):
        # NOTE: Seems to be a bug in Pyre where you can't set the port.
        if port is not None:
            raise NotImplementedError('There is a bug in Pyre that prevents setting of the discovery port. If you require multiple federations of Pyre components, use prefix instead of port in Transport constructor.')

        # dict of remote name to callback. See subscribe method above.
        self._subscribers = {}
        
        # Callback for all message (or None if none registered)
        self._subscribe_all = None

        self._prefix = prefix

        # Attach the federation name as a prefix to both this channel
        # and the global channel. The global channel is currently
        # just used for QUIT messages.

        if prefix is not None:
            myname = prefix + myname
            self._globalchannel = prefix + "GLOBAL"
        else:
            self._globalchannel = "GLOBAL"

        self._pyre = Pyre(myname)
        if port is not None:
            self._pyre.set_port(port)

        self._pyre.join(myname)
        self._pyre.join(self._globalchannel)
        self._pyre.start()

        # Dict of (UUIDs => IP addresses) that have sent a valid ENTER message
        self._uuid2ip = {}

        self._run = True

        self._readthread = threading.Thread(target=self._readworker)
        self._readthread.start()
示例#22
0
    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)
示例#23
0
class Time_Sync(Plugin):
    """Synchronize time across local network.

    Implements the Pupil Time Sync protocol.
    Acts as clock service and as follower if required.
    See `time_sync_spec.md` for details.
    """

    icon_chr = chr(0xEC15)
    icon_font = "pupil_icons"

    def __init__(self,
                 g_pool,
                 node_name=None,
                 sync_group_prefix="default",
                 base_bias=1.0):
        super().__init__(g_pool)
        self.sync_group_prefix = sync_group_prefix
        self.discovery = None

        self.leaderboard = []
        self.has_been_master = 0.0
        self.has_been_synced = 0.0
        self.tie_breaker = random.random()
        self.base_bias = base_bias

        self.sync_group_members = {}

        self.master_service = Clock_Sync_Master(self.g_pool.get_timestamp)
        self.follower_service = None  # only set if there is a better server than us

        self.restart_discovery(node_name)

    @property
    def sync_group(self):
        return self.sync_group_prefix + "-time_sync-" + __protocol_version__

    @sync_group.setter
    def sync_group(self, full_name):
        self.sync_group_prefix = full_name.rsplit("-time_sync-" +
                                                  __protocol_version__,
                                                  maxsplit=1)[0]

    def init_ui(self):
        self.add_menu()
        self.menu.label = "Network Time Sync"
        help_str = "Synchonize time of Pupil Captures across the local network."
        self.menu.append(
            ui.Info_Text("Protocol version: " + __protocol_version__))

        self.menu.append(ui.Info_Text(help_str))
        help_str = "All pupil nodes of one group share a Master clock."
        self.menu.append(ui.Info_Text(help_str))
        self.menu.append(
            ui.Text_Input("node_name",
                          self,
                          label="Node Name",
                          setter=self.restart_discovery))
        self.menu.append(
            ui.Text_Input(
                "sync_group_prefix",
                self,
                label="Sync Group",
                setter=self.change_sync_group,
            ))

        def sync_status():
            if self.follower_service:
                return str(self.follower_service)
            else:
                return "Clock Master"

        self.menu.append(
            ui.Text_Input("sync status",
                          getter=sync_status,
                          setter=lambda _: _,
                          label="Status"))

        def set_bias(bias):
            if bias < 0:
                bias = 0.0
            self.base_bias = bias
            self.announce_clock_master_info()
            self.evaluate_leaderboard()

        help_str = "The clock service with the highest bias becomes clock master."
        self.menu.append(ui.Info_Text(help_str))
        self.menu.append(
            ui.Text_Input("base_bias",
                          self,
                          label="Master Bias",
                          setter=set_bias))
        self.menu.append(
            ui.Text_Input("leaderboard", self, label="Master Nodes in Group"))
        self.sync_group_members_menu = ui.Growing_Menu("Sync Group Members")
        self.menu.append(self.sync_group_members_menu)

    def recent_events(self, events):
        should_announce = False
        for evt in self.discovery.recent_events():
            if evt.type == "SHOUT":
                try:
                    self.update_leaderboard(evt.peer_uuid, evt.peer_name,
                                            float(evt.msg[0]), int(evt.msg[1]))
                except Exception as e:
                    logger.debug("Garbage raised `{}` -- dropping.".format(e))
                self.evaluate_leaderboard()
            elif evt.type == "JOIN" and evt.group == self.sync_group:
                should_announce = True
                self.insert_sync_group_member(evt.peer_uuid, evt.peer_name)
            elif (evt.type == "LEAVE"
                  and evt.group == self.sync_group) or evt.type == "EXIT":
                self.remove_from_leaderboard(evt.peer_uuid)
                self.evaluate_leaderboard()
                self.remove_sync_group_member(evt.peer_uuid)

        if should_announce:
            self.announce_clock_master_info()

        if (not self.has_been_synced and self.follower_service
                and self.follower_service.in_sync):
            self.has_been_synced = 1.0
            self.announce_clock_master_info()
            self.evaluate_leaderboard()

    def update_leaderboard(self, uuid, name, rank, port):
        for cs in self.leaderboard:
            if cs.uuid == uuid:
                if (cs.rank != rank) or (cs.port != port):
                    self.remove_from_leaderboard(cs.uuid)
                    break
                else:
                    # no changes. Just leave as is
                    return

        # clock service was not encountered before or has changed adding it to leaderboard
        cs = Clock_Service(uuid, name, rank, port)
        heappush(self.leaderboard, cs)
        logger.debug("{} added".format(cs))

    def remove_from_leaderboard(self, uuid):
        for cs in self.leaderboard:
            if cs.uuid == uuid:
                self.leaderboard.remove(cs)
                logger.debug("{} removed".format(cs))
                break

    def evaluate_leaderboard(self):
        if not self.leaderboard:
            logger.debug("nobody on the leader board.")
            return

        current_leader = self.leaderboard[0]
        if self.discovery.uuid() != current_leader.uuid:
            # we are not the leader!
            leader_ep = self.discovery.peer_address(current_leader.uuid)
            leader_addr = urlparse(leader_ep).netloc.split(":")[0]
            if self.follower_service is None:
                # make new follower
                self.follower_service = Clock_Sync_Follower(
                    leader_addr,
                    port=current_leader.port,
                    interval=10,
                    time_fn=self.get_time,
                    jump_fn=self.jump_time,
                    slew_fn=self.slew_time,
                )
            else:
                # update follower_service
                self.follower_service.host = leader_addr
                self.follower_service.port = current_leader.port
            return

        # we are the leader
        logger.debug("we are the leader")
        if self.follower_service is not None:
            self.follower_service.terminate()
            self.follower_service = None

        if not self.has_been_master:
            self.has_been_master = 1.0
            logger.debug("Become clock master with rank {}".format(self.rank))
            self.announce_clock_master_info()

    def insert_sync_group_member(self, uuid, name):
        member_text = ui.Info_Text(name)
        self.sync_group_members[uuid] = member_text
        self.sync_group_members_menu.append(member_text)
        self.sync_group_members_menu.elements.sort(
            key=lambda text_field: text_field.text)

    def insert_all_sync_group_members_from_group(self, group):
        for uuid in self.discovery.peers_by_group(group):
            name = self.discovery.get_peer_name(uuid)
            self.insert_sync_group_member(uuid, name)

    def remove_all_sync_group_members(self):
        for uuid in list(self.sync_group_members.keys()):
            self.remove_sync_group_member(uuid)

    def remove_sync_group_member(self, uuid):
        try:
            self.sync_group_members_menu.remove(self.sync_group_members[uuid])
            del self.sync_group_members[uuid]
        except KeyError:
            logger.debug("Peer has already been removed from members list.")

    def announce_clock_master_info(self):
        self.discovery.shout(
            self.sync_group,
            [
                repr(self.rank).encode(),
                repr(self.master_service.port).encode()
            ],
        )
        self.update_leaderboard(self.discovery.uuid(), self.node_name,
                                self.rank, self.master_service.port)

    @property
    def rank(self):
        return (4 * self.base_bias + 2 * self.has_been_master +
                self.has_been_synced + self.tie_breaker)

    def get_time(self):
        return self.g_pool.get_timestamp()

    def slew_time(self, offset):
        self.g_pool.timebase.value += offset

    def jump_time(self, offset):
        ok_to_change = True
        for p in self.g_pool.plugins:
            if p.class_name == "Recorder":
                if p.running:
                    ok_to_change = False
                    logger.error(
                        "Request to change timebase during recording ignored. Turn off recording first."
                    )
                    break
        if ok_to_change:
            self.slew_time(offset)
            logger.info(
                "Pupil Sync has adjusted the clock by {}s".format(offset))
            return True
        else:
            return False

    def restart_discovery(self, name):

        if self.discovery:
            if self.discovery.name() == name:
                return
            else:
                self.remove_all_sync_group_members()
                self.discovery.leave(self.sync_group)
                self.discovery.stop()
                self.leaderboard = []

        self.node_name = name or gethostname()
        self.discovery = Pyre(self.node_name)
        # Either joining network for the first time or rejoining the same group.
        self.discovery.join(self.sync_group)
        self.discovery.start()
        self.announce_clock_master_info()

    def change_sync_group(self, new_group_prefix):
        if new_group_prefix != self.sync_group_prefix:
            self.remove_all_sync_group_members()
            self.discovery.leave(self.sync_group)
            self.leaderboard = []
            if self.follower_service:
                self.follower_service.terminate()
                self.follower = None
            self.sync_group_prefix = new_group_prefix
            self.discovery.join(self.sync_group)
            self.insert_all_sync_group_members_from_group(self.sync_group)
            self.announce_clock_master_info()

    def deinit_ui(self):
        for uuid in list(self.sync_group_members.keys()):
            self.remove_sync_group_member(uuid)
        self.remove_menu()

    def get_init_dict(self):
        return {
            "node_name": self.node_name,
            "sync_group_prefix": self.sync_group_prefix,
            "base_bias": self.base_bias,
        }

    def cleanup(self):
        self.discovery.leave(self.sync_group)
        self.discovery.stop()
        self.master_service.stop()
        if self.follower_service:
            self.follower_service.stop()
        self.master_service = None
        self.follower_service = None
        self.discovery = None
示例#24
0
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])
示例#25
0
class Time_Sync(Plugin):
    """Synchronize time across local network.

    Implements the Pupil Time Sync protocol.
    Acts as clock service and as follower if required.
    See `time_sync_spec.md` for details.
    """

    def __init__(self, g_pool, node_name=None, sync_group_prefix='default', base_bias=1.):
        super().__init__(g_pool)
        self.menu = None
        self.sync_group_prefix = sync_group_prefix
        self.discovery = None

        self.leaderboard = []
        self.has_been_master = 0.
        self.has_been_synced = 0.
        self.tie_breaker = random.random()
        self.base_bias = base_bias

        self.master_service = Clock_Sync_Master(self.g_pool.get_timestamp)
        self.follower_service = None  # only set if there is a better server than us

        self.restart_discovery(node_name)

    @property
    def sync_group(self):
        return self.sync_group_prefix + '-time_sync-' + __protocol_version__

    @sync_group.setter
    def sync_group(self, full_name):
        self.sync_group_prefix = full_name.rsplit('-time_sync-' + __protocol_version__, maxsplit=1)[0]

    def init_gui(self):
        def close():
            self.alive = False

        help_str = "Synchonize time of Pupil Captures across the local network."
        self.menu = ui.Growing_Menu('Network Time Sync')
        self.menu.collapsed = True
        self.menu.append(ui.Button('Close', close))
        self.menu.append(ui.Info_Text('Protocol version: ' + __protocol_version__))

        self.menu.append(ui.Info_Text(help_str))
        help_str = "All pupil nodes of one group share a Master clock."
        self.menu.append(ui.Info_Text(help_str))
        self.menu.append(ui.Text_Input('node_name', self, label='Node Name', setter=self.restart_discovery))
        self.menu.append(ui.Text_Input('sync_group_prefix', self, label='Sync Group', setter=self.change_sync_group))

        def sync_status():
            if self.follower_service:
                return str(self.follower_service)
            else:
                return 'Clock Master'
        self.menu.append(ui.Text_Input('sync status', getter=sync_status, setter=lambda _: _, label='Status'))

        def set_bias(bias):
            if bias < 0:
                bias = 0.
            self.base_bias = bias
            self.announce_clock_master_info()
            self.evaluate_leaderboard()

        help_str = "The clock service with the highest bias becomes clock master."
        self.menu.append(ui.Info_Text(help_str))
        self.menu.append(ui.Text_Input('base_bias', self, label='Master Bias', setter=set_bias))
        self.menu.append(ui.Text_Input('leaderboard', self, label='Master Nodes in Group'))
        self.g_pool.sidebar.append(self.menu)

    def recent_events(self, events):
        should_announce = False
        for evt in self.discovery.recent_events():
            if evt.type == 'SHOUT':
                try:
                    self.update_leaderboard(evt.peer_uuid, evt.peer_name, float(evt.msg[0]), int(evt.msg[1]))
                except Exception as e:
                    logger.debug('Garbage raised `{}` -- dropping.'.format(e))
                self.evaluate_leaderboard()
            elif evt.type == 'JOIN' and evt.group == self.sync_group:
                should_announce = True
            elif (evt.type == 'LEAVE' and evt.group == self.sync_group) or evt.type == 'EXIT':
                self.remove_from_leaderboard(evt.peer_uuid)
                self.evaluate_leaderboard()

        if should_announce:
            self.announce_clock_master_info()

        if not self.has_been_synced and self.follower_service and self.follower_service.in_sync:
            self.has_been_synced = 1.
            self.announce_clock_master_info()
            self.evaluate_leaderboard()

    def update_leaderboard(self, uuid, name, rank, port):
        for cs in self.leaderboard:
            if cs.uuid == uuid:
                if (cs.rank != rank) or (cs.port != port):
                    self.remove_from_leaderboard(cs.uuid)
                    break
                else:
                    # no changes. Just leave as is
                    return

        # clock service was not encountered before or has changed adding it to leaderboard
        cs = Clock_Service(uuid, name, rank, port)
        heappush(self.leaderboard, cs)
        logger.debug('{} added'.format(cs))

    def remove_from_leaderboard(self, uuid):
        for cs in self.leaderboard:
            if cs.uuid == uuid:
                self.leaderboard.remove(cs)
                logger.debug('{} removed'.format(cs))
                break

    def evaluate_leaderboard(self):
        if not self.leaderboard:
            logger.debug("nobody on the leader board.")
            return

        current_leader = self.leaderboard[0]
        if self.discovery.uuid() != current_leader.uuid:
            # we are not the leader!
            leader_ep = self.discovery.peer_address(current_leader.uuid)
            leader_addr = urlparse(leader_ep).netloc.split(':')[0]
            if self.follower_service is None:
                # make new follower
                self.follower_service = Clock_Sync_Follower(leader_addr,
                                                            port=current_leader.port,
                                                            interval=10,
                                                            time_fn=self.get_time,
                                                            jump_fn=self.jump_time,
                                                            slew_fn=self.slew_time)
            else:
                # update follower_service
                self.follower_service.host = leader_addr
                self.follower_service.port = current_leader.port
            return

        # we are the leader
        logger.debug("we are the leader")
        if self.follower_service is not None:
            self.follower_service.terminate()
            self.follower_service = None

        if not self.has_been_master:
            self.has_been_master = 1.
            logger.debug('Become clock master with rank {}'.format(self.rank))
            self.announce_clock_master_info()

    def announce_clock_master_info(self):
        self.discovery.shout(self.sync_group, [repr(self.rank).encode(),
                                               repr(self.master_service.port).encode()])
        self.update_leaderboard(self.discovery.uuid(), self.node_name, self.rank, self.master_service.port)

    @property
    def rank(self):
        return 4*self.base_bias + 2*self.has_been_master + self.has_been_synced + self.tie_breaker

    def get_time(self):
        return self.g_pool.get_timestamp()

    def slew_time(self, offset):
        self.g_pool.timebase.value += offset

    def jump_time(self, offset):
        ok_to_change = True
        for p in self.g_pool.plugins:
            if p.class_name == 'Recorder':
                if p.running:
                    ok_to_change = False
                    logger.error("Request to change timebase during recording ignored. Turn off recording first.")
                    break
        if ok_to_change:
            self.slew_time(offset)
            logger.info("Pupil Sync has adjusted the clock by {}s".format(offset))
            return True
        else:
            return False

    def restart_discovery(self, name):

        if self.discovery:
            if self.discovery.name() == name:
                return
            else:
                self.discovery.leave(self.sync_group)
                self.discovery.stop()
                self.leaderboard = []

        self.node_name = name or gethostname()
        self.discovery = Pyre(self.node_name)
        # Either joining network for the first time or rejoining the same group.
        self.discovery.join(self.sync_group)
        self.discovery.start()
        self.announce_clock_master_info()

    def change_sync_group(self, new_group_prefix):
        if new_group_prefix != self.sync_group_prefix:
            self.discovery.leave(self.sync_group)
            self.leaderboard = []
            if self.follower_service:
                self.follower_service.terminate()
                self.follower = None
            self.sync_group_prefix = new_group_prefix
            self.discovery.join(self.sync_group)
            self.announce_clock_master_info()

    def deinit_gui(self):
        if self.menu:
            self.g_pool.sidebar.remove(self.menu)
            self.menu = None

    def get_init_dict(self):
        return {'node_name': self.node_name,
                'sync_group_prefix': self.sync_group_prefix,
                'base_bias': self.base_bias}

    def cleanup(self):
        self.deinit_gui()
        self.discovery.leave(self.sync_group)
        self.discovery.stop()
        self.master_service.stop()
        if self.follower_service:
            self.follower_service.stop()
        self.master_service = None
        self.follower_service = None
        self.discovery = None
示例#26
0
def chat_task(ctx, pipe):
    print("-----CAR PEER COMMUNICATION STARTED-----")
    print("Manufacturer: ", MANUFACTURER, " - Model: ", MODEL)

    connected_cars = 0

    #Set up node for the car
    n = Pyre("")
    n.set_header("manufacturer", MANUFACTURER)
    n.set_header("model", MODEL)

    #Join the group 'chat'
    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, that we want to shout on the network
        if pipe in items:
            message = pipe.recv()

            # User stopped car
            if message.decode('utf-8') == STOP_COMMAND:
                break

            print(">>>>>> Sending out shout: %s" % message)
            n.shouts(GROUPNAME, message.decode('utf-8'))

        # Received messages from system or messages from other peers
        else:
            cmds = n.recv()
            print("--------------------------------------------------------------------------------")
            #print(">>>>>>>RECEIVED MESSAGE: ", cmds)

            msg_type = cmds.pop(0)
            car_uuid = uuid.UUID(bytes=cmds.pop(0))
            msg_name = cmds.pop(0)

            if msg_type.decode('utf-8') == "ENTER":
                headers = json.loads(cmds.pop(0).decode('utf-8'))
                print(">>>> NEW CAR DISCOVERED IN NETWORK")
                print("---Manufacturer:", headers.get("manufacturer"), "--- Model:", headers.get("model"))

            elif msg_type.decode('utf-8') == "JOIN":
                print(">>>> NEW CAR JOINED GROUP <<", cmds.pop(0).decode('utf-8'),">>")
                connected_cars += 1

            elif msg_type.decode('utf-8') == "SHOUT":
                print(">>>> RECEIVED SHOUT IN %s" % cmds.pop(0))
                print("---Msg: %s" % cmds.pop(0))

            elif msg_type.decode('utf-8') == "EXIT":
                print(">>>> CAR LEFT NETWORK")
                connected_cars -= 1


            print("---Total connected cars: ", connected_cars)
            print("---Car_UUID: ", car_uuid)
            #print("---NODE_MSG REMAINING: %s" % cmds)


    print("-----CAR COMMUNICATION STOPPED-----")
    n.stop()
示例#27
0
    def thread_loop(self, context, pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()
        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(n.socket(), zmq.POLLIN)

        front, back = zhelper.zcreate_pipe(context)
        poller.register(back, zmq.POLLIN)

        def wake_up():
            #on app close this timer calls a closed socket. We simply catch it here.

            try:
                front.send('wake_up')
            except Exception as e:
                logger.debug('Orphaned timer thread raised error: %s' % e)

        t = Timer(self.time_sync_announce_interval, wake_up)
        t.daemon = True
        t.start()

        while (True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll())
            except zmq.ZMQError:
                logger.warning('Socket fail.')
                continue

            if back in items and items[back] == zmq.POLLIN:
                back.recv()
                #timeout events are used for pupil sync.
                #annouce masterhood every interval time:
                if isinstance(self.time_sync_node, Clock_Sync_Master):
                    n.shouts(
                        self.group, SYNC_TIME_MASTER_ANNOUNCE +
                        "%s" % self.clock_master_worthiness() + msg_delimeter +
                        '%s' % self.time_sync_node.port)

                # synced slave: see if we should become master if we dont hear annoncement within time.
                elif isinstance(self.time_sync_node, Clock_Sync_Follower
                                ) and not self.time_sync_node.offset_remains:
                    if self.get_unadjusted_time(
                    ) - self.last_master_announce > self.time_sync_wait_interval_short:
                        self.time_sync_node.terminate()
                        self.time_sync_node = Clock_Sync_Master(
                            time_fn=self.get_time)
                        n.shouts(
                            self.group, SYNC_TIME_MASTER_ANNOUNCE +
                            "%s" % self.clock_master_worthiness() +
                            msg_delimeter + '%s' % self.time_sync_node.port)

                # unsynced slave or none should wait longer but eventually take over
                elif self.get_unadjusted_time(
                ) - self.last_master_announce > self.time_sync_wait_interval_long:
                    if self.time_sync_node:
                        self.time_sync_node.terminate()
                    self.time_sync_node = Clock_Sync_Master(
                        time_fn=self.get_time)
                    n.shouts(
                        self.group, SYNC_TIME_MASTER_ANNOUNCE +
                        "%s" % self.clock_master_worthiness() + msg_delimeter +
                        '%s' % self.time_sync_node.port)

                t = Timer(self.time_sync_announce_interval, wake_up)
                t.daemon = True
                t.start()

            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == exit_thread:
                    break
                else:
                    logger.debug("Shout '%s' to '%s' " % (message, self.group))
                    n.shouts(self.group, message)
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uuid, name, group, msg = cmds
                    logger.debug("'%s' shouts '%s'." % (name, msg))
                    self._handle_msg(uuid, name, msg, n)

                elif msg_type == "WHISPER":
                    uuid, name, msg = cmds
                    logger.debug("'%s/' whispers '%s'." % (name, msg))
                    self._handle_msg_whisper(uuid, name, msg, n)

                elif msg_type == "JOIN":
                    uuid, name, group = cmds
                    if group == self.group:
                        self.group_members[uuid] = name
                        self.update_gui()

                elif msg_type == "EXIT":
                    uuid, name = cmds
                    try:
                        del self.group_members[uuid]
                    except KeyError:
                        pass
                    else:
                        self.update_gui()

                # elif msg_type == "LEAVE":
                #     uuid,name,group = cmds
                # elif msg_type == "ENTER":
                #     uuid,name,headers,ip = cmds
                #     logger.warning((uuid,'name',headers,ip))
            else:
                pass

        logger.debug('thread_loop closing.')

        self.thread_pipe = None
        n.stop()
示例#28
0
    def thread_loop(self,context,pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        logger.debug(n.socket())
        poller.register(n.socket(), zmq.POLLIN)
        while(True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll())
            except zmq.ZMQError:
                logger.warning('Socket fail.')
            # print(n.socket(), items)
            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == "EXIT_THREAD":
                    break
                logger.debug("Emitting to '%s' to '%s' " %(message,self.group))
                n.shouts(self.group, message)
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uid,name,group,msg = cmds
                    logger.debug("'%s' shouts '%s'."%(name,msg))
                    if start_rec in msg :
                        session_name = msg.replace(start_rec,'')
                        self.notify_all({'name':'rec_should_start','session_name':session_name,'network_propagate':False})
                    elif stop_rec in msg:
                        self.notify_all({'name':'rec_should_stop','network_propagate':False})
                    elif sync_time in msg:
                        offset = float(msg.replace(sync_time,''))
                        if self.ok_to_set_timebase():
                            self.adjust_timebase(offset)

                elif msg_type == "ENTER":
                    uid,name,headers,ip = cmds
                elif msg_type == "JOIN":
                    uid,name,group = cmds
                    if group == self.group:
                        self.group_members[uid] = name
                        self.update_gui()
                elif msg_type == "EXIT":
                    uid,name = cmds
                    try:
                        del self.group_members[uid]
                    except KeyError:
                        pass
                    else:
                        self.update_gui()
                elif msg_type == "LEAVE":
                    uid,name,group = cmds
                elif msg_tpye == "WHISPER":
                    pass

        logger.debug('thread_loop closing.')
        self.thread_pipe = None
        n.stop()
示例#29
0
    def thread_loop(self,context,pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()
        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        logger.debug(n.socket())
        poller.register(n.socket(), zmq.POLLIN)

        while(True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll(self.timeout))
            except zmq.ZMQError:
                logger.warning('Socket fail.')
            # print(n.socket(), items)
            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == exit_thread:
                    break
                elif message.decode('utf-8') == init_master_sync:
                    self.timeout = 3000
                else:
                    logger.debug("Emitting to '%s' to '%s' " %(message,self.group))
                    n.shouts(self.group, message)
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uid,name,group,msg = cmds
                    logger.debug("'%s' shouts '%s'."%(name,msg))
                    self.handle_msg(name,msg)

                elif msg_type == "WHISPER":
                    uid,name,msg = cmds
                    logger.debug("'%s/' whispers '%s'."%(name,msg))
                    self.handle_msg_whisper(uid,name,msg,n)

                elif msg_type == "JOIN":
                    uid,name,group = cmds
                    if group == self.group:
                        self.group_members[uid] = name
                        self.update_gui()

                elif msg_type == "EXIT":
                    uid,name = cmds
                    try:
                        del self.group_members[uid]
                    except KeyError:
                        pass
                    else:
                        self.update_gui()

                # elif msg_type == "LEAVE":
                #     uid,name,group = cmds
                # elif msg_type == "ENTER":
                #     uid,name,headers,ip = cmds
                #     logger.warning((uid,'name',headers,ip))

            elif not items:
                #timeout events are used for pupil sync.
                if self.sync_master is self:
                    if self.sync_nodes:
                        node_uid = self.sync_nodes.pop(0)
                        logger.info("Synchonizing node %s"%self.group_members[node_uid])
                        n.whispers(uuid.UUID(bytes=node_uid),sync_time_init)
                    else:
                        self.timeout = None
                        self.sync_master = None
                        logger.info("All other Pupil nodes are sycronized.")
                elif self.sync_master:
                    t0 = self.g_pool.capture.get_timestamp()
                    n.whispers(uuid.UUID(bytes=self.sync_master),sync_time_request+'%s'%t0)

            else:
                pass

        logger.debug('thread_loop closing.')
        self.thread_pipe = None
        n.stop()
示例#30
0
def chat_task(ctx, pipe, ncmds):
    n = Pyre(ctx)
    n.join("CHAT")
    n.start()

    # wait for someone else to join the chat
    while not n.get_peer_groups():
        pass

    pipe.send('ready'.encode('utf-8'))
    cmds = 0
    t0 = time.time()

    poller = zmq.Poller()
    poller.register(pipe, zmq.POLLIN)
    poller.register(n.inbox, zmq.POLLIN)
    while(True):
        items = dict(poller.poll())
        if pipe in items and items[pipe] == zmq.POLLIN:
            message = pipe.recv()
            # message to quit
            if message.decode('utf-8') == "$$STOP":
                break
            n.shout("CHAT", message)
        if n.inbox in items and items[n.inbox] == zmq.POLLIN:
            n.recv()
            cmds += 1
            if cmds == ncmds:
                msg = 'Got %s msgs in %0.2f sec' % (cmds, time.time() - t0)
                pipe.send(msg.encode('utf-8'))
    n.stop()
示例#31
0
    def __init__(self, channel=ZYRE_CHANNEL, *args, **kvargs):

        self.logger = logging.getLogger('pyre')
        self.channel = channel
        self.engine = Pyre(self.channel)
        self.id = self.engine.uuid()
示例#32
0
def chat_task(ctx, pipe, ncmds):
    n = Pyre(ctx=ctx)
    n.join("CHAT")
    n.start()

    # wait for someone else to join the chat
    while not n.peer_groups():
        pass

    pipe.send('ready'.encode('utf-8'))
    cmds = 0
    t0 = time.time()

    poller = zmq.Poller()
    poller.register(pipe, zmq.POLLIN)
    poller.register(n.inbox, zmq.POLLIN)
    while (True):
        items = dict(poller.poll())
        if pipe in items and items[pipe] == zmq.POLLIN:
            message = pipe.recv()
            # message to quit
            if message.decode('utf-8') == "$$STOP":
                break
            n.shout("CHAT", message)
        if n.inbox in items and items[n.inbox] == zmq.POLLIN:
            n.recv()
            cmds += 1
            if cmds == ncmds:
                msg = 'Got %s msgs in %0.2f sec' % (cmds, time.time() - t0)
                pipe.send(msg.encode('utf-8'))
    n.stop()
示例#33
0
文件: network.py 项目: vedb/pyndsi
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]
示例#34
0
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()
示例#35
0
def run_time_sync_master(group):

    pts_group = group + '-time_sync-v1'

    # the time source in the example is python time.time you can change this.
    # replace with an implementation that give your custom time in floating sec.
    clock_service = Clock_Sync_Master(time)

    # This example is a clock service only, not a clock follower.
    # Therefore the rank is designed to always trump all others.
    rank = 1000
    discovery = Pyre('pupil-helper-service')
    discovery.join(pts_group)
    discovery.start()
    logger.info('Joining "{}" group with rank {}'.format(pts_group, rank))

    def announce_clock_service_info():
        discovery.shout(
            pts_group,
            [repr(rank).encode(),
             repr(clock_service.port).encode()])

    try:
        for event in discovery.events():
            if event.type == 'JOIN' and event.group == pts_group:
                logger.info(
                    '"{}" joined "{}" group. Announcing service.'.format(
                        event.peer_name, pts_group))
                announce_clock_service_info()
    except KeyboardInterrupt:
        pass
    finally:
        logger.info('Leaving "{}" group'.format(pts_group))
        discovery.leave(pts_group)
        discovery.stop()
        clock_service.stop()
示例#36
0
    def gaze_exchange_task(self, ctx, pipe):
        """
        Task for exchanging messages
        Args:
            ctx(zmq.Context): the zmq context
            pipe(zmq.PAIR pipe): the pipe for exchanging messages
        Returns: (zmq.PAIR pipe) the pipe
        """
        n = Pyre("GAZE_EXCHANGE")
        self.publisher_id = n.uuid()
        n.join(GROUP_GAZE_EXCHANGE)
        n.start()

        poller = zmq.Poller()
        # noinspection PyUnresolvedReferences
        poller.register(pipe, zmq.POLLIN)
        # noinspection PyUnresolvedReferences
        poller.register(n.socket(), zmq.POLLIN)
        while not self.stopped:
            items = dict(poller.poll())
            print(n.socket(), items)
            # noinspection PyUnresolvedReferences
            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                message = message.decode('utf-8')
                if message == STOP_MESSAGE:
                    break
                print("GAZE_EXCHANGE_TASK: {}".format(message))
                self.save_gaze_from_message(message)
                n.shouts(GROUP_GAZE_EXCHANGE, message)
            else:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                print("NODE_MSG TYPE: %s" % msg_type)
                print("NODE_MSG PEER: %s" % uuid.UUID(bytes=cmds.pop(0)))
                print("NODE_MSG NAME: %s" % cmds.pop(0))
                if msg_type.decode('utf-8') == "SHOUT":
                    print("NODE_MSG GROUP: %s" % cmds.pop(0))
                    message = cmds.pop(0).decode("utf-8")
                    self.save_gaze_from_message(message)
                elif msg_type.decode('utf-8') == "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)
        n.stop()
示例#37
0
Author: Mohammadali Varfan
Contact information: [email protected]
'''

import pyre
from pyre import Pyre

from pyre import zhelper
import zmq
import uuid
import logging
import sys
import json
import time

n = Pyre("sender_node")
n.join("CHAT")
n.start()

nodes_list = dict()

t = time.localtime()
current_time = str(t[0]) + "-" + str(t[1]) + "-" + str(t[2]) + "T" + str(
    t[3]) + ":" + str(t[4]) + ":" + str(t[5]) + "Z"

features_list = ['robotID', 'sensors', 'timestamp']
start_query_time = "2017-12-10 3:55:40"
end_query_time = "2017-12-10 11:25:40"

msg_data = {
    "header": {
def run_time_sync_follower(time_fn, jump_fn, slew_fn, group):
    """Main follower logic"""

    # Start Pyre node and find clock services in `pts_group`
    pts_group = group + '-time_sync-v1'
    discovery = Pyre('pupil-helper-follower')
    discovery.join(pts_group)
    discovery.start()
    logger.info('Joining "{}" group'.format(pts_group))

    # The leaderboard keeps track of all clock services
    # and is used to determine the clock master
    leaderboard = []
    follower_service = None

    def update_leaderboard(uuid, name, rank, port):
        """Add or update an existing clock service on the leaderboard"""
        for cs in leaderboard:
            if cs.uuid == uuid:
                if (cs.rank != rank) or (cs.port != port):
                    remove_from_leaderboard(cs.uuid)
                    break
                else:
                    # no changes. Just leave as is
                    return

        # clock service was not encountered before or has changed adding it to leaderboard
        cs = Clock_Service(uuid, name, rank, port)
        heappush(leaderboard, cs)
        logger.debug('<{}> added'.format(cs))

    def remove_from_leaderboard(uuid):
        """Remove an existing clock service from the leaderboard"""
        for cs in leaderboard:
            if cs.uuid == uuid:
                leaderboard.remove(cs)
                logger.debug('<{}> removed'.format(cs))
                break

    def evaluate_leaderboard(follower_service):
        """
        Starts/changes/stops the time follower service according to
        who the current clock master is.
        """
        if not leaderboard:
            logger.debug("nobody on the leader board.")
            if follower_service is not None:
                follower_service.terminate()
            return None

        current_leader = leaderboard[0]
        leader_ep = discovery.peer_address(current_leader.uuid)
        leader_addr = urlparse(leader_ep).netloc.split(':')[0]
        logger.info('Following <{}>'.format(current_leader))
        if follower_service is None:
            # make new follower
            follower_service = Clock_Sync_Follower(leader_addr,
                                                   port=current_leader.port,
                                                   interval=10,
                                                   time_fn=time_fn,
                                                   jump_fn=jump_fn,
                                                   slew_fn=slew_fn)
        else:
            # update follower_service
            follower_service.host = leader_addr
            follower_service.port = current_leader.port

        return follower_service

    try:
        # wait for the next Pyre event
        for event in discovery.events():
            if event.type == 'SHOUT':
                # clock service announcement
                # ill-formatted messages will be dropped
                try:
                    update_leaderboard(event.peer_uuid,
                                       event.peer_name,
                                       float(event.msg[0]),
                                       int(event.msg[1]))
                except Exception as e:
                    logger.debug('Garbage raised `{}` -- dropping.'.format(e))
                follower_service = evaluate_leaderboard(follower_service)
            elif ((event.type == 'LEAVE' and event.group == pts_group)
                    or event.type == 'EXIT'):
                remove_from_leaderboard(event.peer_uuid)
                follower_service = evaluate_leaderboard(follower_service)

    except KeyboardInterrupt:
        pass
    finally:
        discovery.leave(pts_group)
        discovery.stop()
        if follower_service is not None:
            follower_service.terminate()
    def discovery_task(self, ctx, pipe):
        self.log.debug("Pyre on iface : {}".format(self.iface))
        n = Pyre(self.groupName, sel_iface=self.iface)
        n.set_header("DISCOVERY_Header1","DISCOVERY_HEADER")
        n.join(self.groupName)
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)

        while(True):
            items = dict(poller.poll())

            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == "$$STOP":
                    break

                n.shout(self.groupName, message)

        n.stop()
class Transport():
    '''Message transport mechanisms for LCAS'''

    def send(self, dest, ntuple):
        '''Send given ntuple to Transport named dest. If dest isn't listening for messages from this Transport, the message will (currently) be silently ignored.'''
        if self._prefix is not None:
            dest = self._prefix + dest
        self._pyre.shout(dest, json.dumps(ntuple).encode('utf-8'))
    # send()

    # Notes on subscribe
    #
    # The callback is called in the same thread that listens for pyre
    # messages, so the callback should start a new thread if it's
    # going to block or take a long time to run.
    #
    # The callback must take one positional argument, the tuple, and
    # can OPTIONALLY take a keyword argument (e.g. **kw). I use the
    # inspect module to detect this. May be too clever for my own
    # good.
    #
    # There can be only one callback for a given remote. If you call
    # subscribe again with the same remote, it raises an error.

    def subscribe(self, remote, callback):
        '''When a message is sent from a Transport named remote to this transport, call the passed callback with the ntuple as the first argument. If the callback takes **kw, it will also pass additional metadata such as the Transport name, UUID, and IP of the sender.'''
        if self._prefix is not None:
            remote = self._prefix + remote
        if remote in self._subscribers:
            raise TransportError(self, 'Transport.subscribe() was called a second time with the same remote (\"%s\"). You must call Transport.unsubscribe() before setting a new callback.'%(remote))
        self._subscribers[remote] = callback
    # subscribe()

    def unsubscribe(self, remote):
        '''Stop listening for messages from remote.'''
        if self._prefix is not None:
            remote = self._prefix + remote
        if remote in self._subscribers:
            del self._subscribers[remote]
    # unsubscribe()

    def subscribe_all(self, callback):
        '''Call callback every time a message is sent from any remote Transport to this Transport.'''
        if self._subscribe_all is not None:
            raise TransportError(self, 'Transport.subscribe_all() was called a second time. You must call Transport.unsubscribe_all() before setting a new callback.')
        self._subscribe_all = callback
    # subscribe_all()

    def unsubscribe_all(self):
        self._subscribe_all = None
    # unsubscribe_all()

    # Notes on get()
    #    
    # If you already subscribe to remote, temporarly overrides
    # the subscribe. The subscribed callback will NOT be called.
    # The subscription is replaced after get() returns.

    def get(self, remote):
        '''Block waiting for a message from a Transport named remote. Returns python namedtuple containing fields object, uuid, name, ip, datetime.'''

        if self._prefix is not None:
            remote = self._prefix + remote

        # The final python namedtuple to be returned needs to be shared
        # between get_callback() and get(). In python3, you can use
        # nonlocal, but in python2 you need a trick (storing in a
        # data structure). The actual value to be returned will
        # be ret[0].
        ret = [ None ]

        # The event e will get set when a message is read by the
        # readthread.
        e = threading.Event()

        # This function is a callback used to detect the next message.
        # It stores the message in a Python namedtuple and sets the
        # event.

        def get_callback(tup, **kw):
            ret[0] = collections.namedtuple('TransportEnvelope', ['object', 'uuid', 'name', 'ip', 'datetime'])(tup, kw['uuid'], kw['name'], kw['ip'], kw['datetime'])
            # Inform get() that ret is ready to be returned.
            e.set()
        # get_callback()

        # Store the old callback, if any
        oldcb = self._subscribers.get(remote, None)

        # Set the subscription
        self._subscribers[remote] = get_callback
        
        # Wait for the callback to be called.
        e.wait()

        # Restore the old subscription, if any.
        if oldcb is not None:
            self._subscribers[remote] = oldcb
        else:
            del self._subscribers[remote]

        # Return the namedtuple.
        return ret[0]
    # get()

    def quit_federation(self):
        '''Send a quit message to all agents in this federation, and then close down the Transport.'''
        if self._run:
            self._pyre.shouts(self._globalchannel, u"QUIT")
            self._run = False
            # Wait for the readthread to finish
            self._readthread.join()
            # Tell Pyre to shut down
            self._pyre.stop()

    def is_running(self):
        '''Return the status of this Transport. If the Transport isn't running, you should not send it messages and the callbacks will not be called.'''
        return self._run

    ######################################################################
    # All private methods below here

    def __init__(self, myname, port=None, prefix=None):
        # NOTE: Seems to be a bug in Pyre where you can't set the port.
        if port is not None:
            raise NotImplementedError('There is a bug in Pyre that prevents setting of the discovery port. If you require multiple federations of Pyre components, use prefix instead of port in Transport constructor.')

        # dict of remote name to callback. See subscribe method above.
        self._subscribers = {}
        
        # Callback for all message (or None if none registered)
        self._subscribe_all = None

        self._prefix = prefix

        # Attach the federation name as a prefix to both this channel
        # and the global channel. The global channel is currently
        # just used for QUIT messages.

        if prefix is not None:
            myname = prefix + myname
            self._globalchannel = prefix + "GLOBAL"
        else:
            self._globalchannel = "GLOBAL"

        self._pyre = Pyre(myname)
        if port is not None:
            self._pyre.set_port(port)

        self._pyre.join(myname)
        self._pyre.join(self._globalchannel)
        self._pyre.start()

        # Dict of (UUIDs => IP addresses) that have sent a valid ENTER message
        self._uuid2ip = {}

        self._run = True

        self._readthread = threading.Thread(target=self._readworker)
        self._readthread.start()
    # __init__()

    # Handle pyre messages. Run in self._readthread
    def _readworker(self):
        '''This method is called in a separate thread to handle messages sent over pyre. It dispataches to methods named for the pyre events (e.g. _ENTER).'''

        # Set up a poller so recv doesn't block. Possibly not needed
        # since we'll always get an event when the other agents quit,
        # but just in case something goes wrong, we want to be sure to
        # close down.

        poller = zmq.Poller()
        sock = self._pyre.socket()
        poller.register(sock, zmq.POLLIN)

        while self._run:
            # Wait until a message is received OR one second timeout.
            items = dict(poller.poll(1000))
            if not (sock in items and items[sock] == zmq.POLLIN):
                # This should only happen if we time out.
                continue
            # There's an event waiting. Read and process it.
            event = self._pyre.recv()
            logger.debug('Transport %s-%s received event %s'%(self._pyre.uuid(), self._pyre.name(), event))
            eventtype = event[0].decode('utf-8')
            # Sender's uuid and name
            sid = uuid.UUID(bytes=event[1])
            name = event[2].decode('utf-8')
            # Make sure we've seen matching ENTER for all events
            if eventtype != 'ENTER' and sid not in self._uuid2ip:
                raise TransportProtocolError(self, 'Received event %s with no matching ENTER.'%(event))
                continue

            if eventtype == 'ENTER':
                # Changed
                url = event[4].decode('utf-8')
                self._ENTER(sid, name, url)
            elif eventtype == 'JOIN':
                channel = event[3].decode('utf-8')
                self._JOIN(sid, name, channel)
            elif eventtype == 'SHOUT':
                channel = event[3].decode('utf-8')
                message = event[4].decode('utf-8')
                if channel == self._globalchannel and message == "QUIT":
                    # Set ourself to stop running, close down pyre, exit
                    # worker thread.
                    self._run = False
                    self._pyre.stop()
                    break
                else:
                    self._SHOUT(sid, name, channel, message)
            elif eventtype == 'WHISPER':
                message = event[3].decode('utf-8')
                self._WHISPER(sid, name, message)
            elif eventtype == 'LEAVE':
                channel = event[3].decode('utf-8')
                self._LEAVE(sid, name, channel)
            elif eventtype == 'EXIT':
                self._EXIT(sid, name)
            else:
                raise TransportProtocolError(self, 'Illegal event type in event %s'%(event))
    # _readworker()

    # The following methods are named for the pyre event that this
    # instance has received. They are called automatically from the
    # worker thread that's listening for events.

    def _ENTER(self, sid, name, url):
        # We expect all connections to be tcp on some port. This regular
        # expression is used to extract the ip part.
        urlmatch = re.match('tcp://([0-9.]+):[0-9]+$', url)
        if urlmatch:
            ip = urlmatch.group(1)
            if is_valid_ip(ip):
                # Everything looks good. Add to list of valid uuids.
                self._uuid2ip[sid] = ip
            else:
                raise TransportSecurityError(self, 'Message from invalid IP address %s in ENTER %s %s %s. Check the function is_valid_ip() in Transport.py.'%(ip, sid, name, url))
        else:
            raise TransportProtocolError(self, 'Malformed URL in ENTER %s %s %s'%(sid, name, url))
    # _ENTER()

    def _JOIN(self, sid, name, channel):
        pass
    # _JOIN()

    def _SHOUT(self, sid, name, channel, message):
        now = datetime.datetime.now()
        logger.debug('In _SHOUT with %s %s %s %s'%(sid, name, channel, message)) #???
        if name in self._subscribers:
            logger.debug('got a subscription')
            cb = self._subscribers[name]
            self._call_callback(cb, sid, name, channel, message, now)
        if self._subscribe_all is not None:
            cb = self._subscribe_all
            self._call_callback(cb, sid, name, channel, message, now)
    # _SHOUT()

    def _call_callback(self, cb, sid, name, channel, message, now):
        if inspect.getargspec(cb).keywords is None:
            cb(json.loads(message))
        else:
            cb(message, uuid=sid, name=name, ip=self._uuid2ip[sid], datetime=now)
    # _call_callback


    def _WHISPER(self, sid, name, message):
        raise TransportProtocolError(self, 'Unexpected WHISPER from %s %s'%(sid, name))
    # _WHISPER()

    def _LEAVE(self, sid, name, channel):
        pass
    # _LEAVE()

    def _EXIT(self, sid, name):
        # Remove sid from list of valid uuids. This should
        # never be an error since we check in _readworker().
        del self._uuid2ip[sid]
def main(argv):

    #if six.PY3:
    #    sys.stderr.write('bridge_client.py currently only supports python2')
    #    sys.exit(1)

    parse_arguments(argv[1:])
    setup_logging()

    # If the user presses ctrl-C, exit cleanly.
    signal.signal(signal.SIGINT, lambda s, f: client_quit())

    # Create the bridge socket
    Global.bridgesocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    Global.bridgesocket.connect((Global.args.host, Global.args.port))

    # Create a pyre instance
    Global.pyre = Pyre()
    Global.pyre.start()

    # Create a poller object that tests if anything is available on
    # any of: 1) The local pyre channels, 2) The bridge socket, 3) stdin.

    poller = zmq.Poller()
    poller.register(Global.pyre.socket(), zmq.POLLIN)
    poller.register(Global.bridgesocket, zmq.POLLIN)
    poller.register(0, zmq.POLLIN)  # stdin

    logging.warning('Starting bridge client to server at %s:%d' %
                    (Global.args.host, Global.args.port))

    while True:
        items = dict(poller.poll())
        logging.debug('Got items =%s' % (items))

        if 0 in items:  # stdin
            # User typed 'quit'. Note: slightly different from
            # a quit message on the global channel in that this
            # doesn't cause remote to quit.
            message = input()
            if message == 'quit':
                client_quit()
            elif message == 'help':
                print(
                    'You can quit the bridge_client (but not the federation) by typing "quit".'
                )
            else:
                print('Unrecognized command %s' % (message))

        if Global.bridgesocket.fileno() in items:
            # Got a message from the remote.
            rec = server_recv()
            logging.debug('Got remote data %s' % (rec))
            if rec[0] == 'JOIN':
                channel = rec[1]
                # If we don't already have a proxy object, create one.
                if channel not in Global.proxies:
                    t = Transport.Transport(channel)
                    Global.pyre.join(channel)
                    Global.proxies[channel] = t
                    Global.proxy_uuids[t._pyre.uuid()] = t
                    logging.info('Creating bridge proxy %s' % (channel))
            elif rec[0] == 'LEAVE':
                # Don't actually know how to handle this.
                pass
            elif rec[0] == 'SHOUT':
                # Use the proxy object to relay the message.
                name = rec[1]
                channel = rec[2]
                message = rec[3]
                if Global.localchannelcount.get(channel, 0) > 0:
                    logging.debug('Bridge proxy shout %s %s %s' %
                                  (name, channel, message))
                    Global.proxies[name].send(channel, message)
            else:
                logging.warning('Unexpected msg %s from client.' % (rec))

        if Global.pyre.socket() in items:
            # Got a message on Pyre.
            event = Global.pyre.recv()
            logging.debug('Got local pyre event %s' % (event))
            eventtype = event[0].decode('utf-8')
            sid = uuid.UUID(bytes=event[1])
            name = event[2].decode('utf-8')

            # Ignore pyre events from proxies
            if sid in Global.proxy_uuids:
                logging.debug('Ignoring proxied pyre event')
                continue

            if eventtype == 'JOIN':
                channel = event[3].decode('utf-8')
                if Global.localchannelcount.get(channel, 0) == 0:
                    Global.pyre.join(channel)
                    Global.localchannelcount[channel] = 0
                    server_send(['JOIN', channel])
                    logging.debug('Bridge client joining local channel %s' %
                                  (channel))
                Global.localchannelcount[channel] += 1
            elif eventtype == 'LEAVE':
                channel = event[3].decode('utf-8')
                Global.localchannelcount[channel] -= 1
                if Global.localchannelcount[channel] == 0:
                    Global.pyre.leave(channel)
                    server_send(['LEAVE', channel])
                    logging.debug('Bridge client leaving channel %s' %
                                  (channel))
            elif eventtype == 'SHOUT':
                channel = event[3].decode('utf-8')

                # Quit if federation QUIT message received.
                if event[4] == u'QUIT':
                    logging.warning(
                        'Bridge client received a local QUIT message. Exiting.'
                    )
                    client_quit()
                # Since the server communicates with json, we
                # need to un-json the message (which server_send
                # will re-json). There's probably a more elegant way
                # to do this.
                if six.PY3:
                    decoded = event[4].decode('utf-8')
                    server_send(['SHOUT', name, channel, decoded])
                else:
                    message = json.loads(event[4].decode('utf-8'))
                    server_send(['SHOUT', name, channel, message])
示例#42
0
Author: Mohammadali Varfan
Contact information: [email protected]
'''

import pyre
from pyre import Pyre

from pyre import zhelper
import zmq
import uuid
import logging
import sys
import json

n = Pyre("receiver_node")
print('Join group [CHAT]')
n.join("CHAT")

print('node START')
n.start()

msg_data = {
    "header": {
        "type": "CMD",
        "version": "0.1.0",
        "metamodel": "ropod-msg-schema.json",
        "msg_id": "0d05d0bc-f1d2-4355-bd88-edf44e2475c8",
        "timestamp": "2017-11-11T11:11:00Z"
    },
    "payload": {
示例#43
0
class Network():
    def __init__(self):
        self.node = Pyre("GAME_NODE")
        self.node.set_header("AUTHORITY", "FALSE")
        self.node.set_header("NAME", "")
        self.node.start()
        self.node.join("world:position")
        self.node.join("world:combat")
        self.node.join("ctf:teams")
        self.node.join("ctf:dropflag")
        self.node.join("ctf:gotflag")
        self.node.join("players:whois")
        self.node.join("player:name")
        self.node.join("ctf:scores")
        self.node.join("ctf:status")

        self.poller = zmq.Poller()
        self.poller.register(self.node.socket(), zmq.POLLIN)

    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
示例#44
0
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()
示例#45
0
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
示例#46
0
    def thread_loop(self,context,pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()
        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(n.socket(), zmq.POLLIN)


        front,back = zhelper.zcreate_pipe(context)
        poller.register(back, zmq.POLLIN)
        def wake_up():
            #on app close this timer calls a closed socket. We simply catch it here.

            try:
                front.send('wake_up')
            except Exception as e:
                logger.debug('Orphaned timer thread raised error: %s'%e)

        t = Timer(self.time_sync_announce_interval, wake_up)
        t.daemon = True
        t.start()

        while(True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll())
            except zmq.ZMQError:
                logger.warning('Socket fail.')
                continue

            if back in items and items[back] == zmq.POLLIN:
                back.recv()
                #timeout events are used for pupil sync.
                #annouce masterhood every interval time:
                if isinstance(self.sync_node,Clock_Sync_Master):
                    n.shouts(self.group, SYNC_TIME_MASTER_ANNOUNCE+"%s"%self.clock_master_worthiness()+msg_delimeter+'%s'%self.sync_node.port)

                # synced slave: see if we should become master if we dont hear annoncement within time.
                elif isinstance(self.sync_node,Clock_Sync_Follower) and not self.sync_node.offset_remains:
                    if self.get_monotonic_time()-self.last_master_announce > self.time_sync_wait_interval_short:
                        self.sync_node.terminate()
                        self.sync_node = Clock_Sync_Master(time_fn=self.get_time)
                        n.shouts(self.group, SYNC_TIME_MASTER_ANNOUNCE+"%s"%self.clock_master_worthiness()+msg_delimeter+'%s'%self.sync_node.port)

                # unsynced slave or none should wait longer but eventually take over
                elif self.get_monotonic_time()-self.last_master_announce > self.time_sync_wait_interval_long:
                    if self.sync_node:
                        self.sync_node.terminate()
                    self.sync_node = Clock_Sync_Master(time_fn=self.get_time)
                    n.shouts(self.group, SYNC_TIME_MASTER_ANNOUNCE+"%s"%self.clock_master_worthiness()+msg_delimeter+'%s'%self.sync_node.port)

                t = Timer(self.time_sync_announce_interval, wake_up)
                t.daemon = True
                t.start()


            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == exit_thread:
                    break
                else:
                    logger.debug("Shout '%s' to '%s' " %(message,self.group))
                    n.shouts(self.group, message)
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uuid,name,group,msg = cmds
                    logger.debug("'%s' shouts '%s'."%(name,msg))
                    self.handle_msg(uuid,name,msg,n)

                elif msg_type == "WHISPER":
                    uuid,name,msg = cmds
                    logger.debug("'%s/' whispers '%s'."%(name,msg))
                    self.handle_msg_whisper(uuid,name,msg,n)

                elif msg_type == "JOIN":
                    uuid,name,group = cmds
                    if group == self.group:
                        self.group_members[uuid] = name
                        self.update_gui()

                elif msg_type == "EXIT":
                    uuid,name = cmds
                    try:
                        del self.group_members[uuid]
                    except KeyError:
                        pass
                    else:
                        self.update_gui()

                # elif msg_type == "LEAVE":
                #     uuid,name,group = cmds
                # elif msg_type == "ENTER":
                #     uuid,name,headers,ip = cmds
                #     logger.warning((uuid,'name',headers,ip))
            else:
                pass

        logger.debug('thread_loop closing.')

        self.thread_pipe = None
        n.stop()
示例#47
0
    def thread_loop(self,context,pipe):
        n = Pyre(self.name)
        n.join(self.group)
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        logger.debug(n.socket())
        poller.register(n.socket(), zmq.POLLIN)
        while(True):
            try:
                #this should not fail but it does sometimes. We need to clean this out.
                # I think we are not treating sockets correclty as they are not thread-save.
                items = dict(poller.poll())
            except zmq.ZMQError:
                logger.warning('Socket fail.')
            # print(n.socket(), items)
            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()
                # message to quit
                if message.decode('utf-8') == "EXIT_THREAD":
                    break
                logger.debug("Emitting to '%s' to '%s' " %(message,self.group))
                n.shouts(self.group, message)
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uid,name,group,msg = cmds
                    logger.debug("'%s' shouts '%s'."%(name,msg))
                    self.handle_msg(name,msg)

                elif msg_type == "WHISPER":
                    pass
                    # uid,name,group,msg = cmds
                    # logger.debug("'%s' whispers '%s'."%(name,msg))
                    # self.handle_msg(name,msg)

                elif msg_type == "JOIN":
                    uid,name,group = cmds
                    if group == self.group:
                        self.group_members[uid] = name
                        self.update_gui()

                elif msg_type == "EXIT":
                    uid,name = cmds
                    try:
                        del self.group_members[uid]
                    except KeyError:
                        pass
                    else:
                        self.update_gui()

                # elif msg_type == "LEAVE":
                #     uid,name,group = cmds
                # elif msg_type == "ENTER":
                #     uid,name,headers,ip = cmds



        logger.debug('thread_loop closing.')
        self.thread_pipe = None
        n.stop()
示例#48
0

def handle_msg(uuid,name,msg,node):
    print UUID(bytes=uuid),name,msg

if __name__ == '__main__':


    logging.basicConfig(level=logging.DEBUG)
    logger = logging.getLogger("pyre")
    logger.setLevel(logging.INFO)
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    ctx = zmq.Context()
    n = Pyre("Script")
    n.join('default group')
    n.start()

    poller = zmq.Poller()
    poller.register(n.socket(), zmq.POLLIN)
    try:
        while(True):
            items = dict(poller.poll(timeout=1000))
            if n.socket() in items and items[n.socket()] == zmq.POLLIN:
                cmds = n.recv()
                msg_type = cmds.pop(0)
                msg_type = msg_type.decode('utf-8')
                if msg_type == "SHOUT":
                    uuid,name,group,msg = cmds
                    handle_msg(uuid,name,msg,n)
示例#49
0
class Client(object):

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.engine.stop()

    def __init__(self, channel=ZYRE_CHANNEL, *args, **kvargs):

        self.logger = logging.getLogger('pyre')
        self.channel = channel
        self.engine = Pyre(self.channel)
        self.id = self.engine.uuid()

    def start(self, ctx, pipe):
        self.logger.info('joining channel')
        self.engine.join(self.channel)

        self.logger.info('starting engine...')
        self.engine.start()

        self.logger.info('id is: {}'.format(self.id))

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(self.engine.socket(), zmq.POLLIN)

        while True:
            items = dict(poller.poll())
            if pipe in items and items[pipe] == zmq.POLLIN:
                message = pipe.recv()

                # message to quit
                if message.decode('utf-8') == "$$STOP":
                    break

                self.logger.info("CHAT_TASK: %s" % message)
                self.engine.shouts(self.channel, message.decode('utf-8'))
            else:
                cmds = self.engine.recv()
                self.logger.info('HMMM {}'.format(cmds))

                msg_type = cmds.pop(0)
                self.logger.info("NODE_MSG TYPE: %s" % msg_type)
                self.logger.info("NODE_MSG PEER: %s" % uuid.UUID(bytes=cmds.pop(0)))
                self.logger.info("NODE_MSG NAME: %s" % cmds.pop(0))

                if msg_type.decode('utf-8') == "SHOUT":
                    self.logger.info("NODE_MSG GROUP: %s" % cmds.pop(0))
                elif msg_type.decode('utf-8') == "ENTER":
                    headers = json.loads(cmds.pop(0).decode('utf-8'))
                    self.logger.info("NODE_MSG HEADERS: %s" % headers)

                    for key in headers:
                        self.logger.info("key = {0}, value = {1}".format(key, headers[key]))

                self.logger.info("NODE_MSG CONT: %s" % cmds)

        self.engine.stop()
示例#50
0
    def network_thread(self, ctx, pipe):
        print("Network thread started..")
        n = Pyre(self.name)
        n.join("Car2X")
        n.start()

        poller = zmq.Poller()
        poller.register(pipe, zmq.POLLIN)
        poller.register(n.inbox, zmq.POLLIN)

        # wait for others
        while not n.peer_groups():
            time.sleep(0.0001)
            pass

        pipe.send('$$ready'.encode('utf-8'))

        while not self.stopped:
            items = dict(poller.poll())

            if pipe in items and items[pipe] == zmq.POLLIN:
                # handle outgoing messages
                try:
                    message = pipe.recv()
                    if message.decode('utf-8') == "$$STOP":
                        break
                    n.shouts("Car2X", message.decode('utf-8'))
                except zmq.error.Again:
                    rospy.logerr("ERROR! Again #1")
            if n.inbox in items and items[n.inbox] == zmq.POLLIN:
                try:
                    cmds = n.recv()

                    msg_type = cmds.pop(0)
                    msg_uuid = cmds.pop(0)
                    msg_name = cmds.pop(0)
                    if msg_type == "JOIN":
                        rospy.loginfo("{} joined!".format(msg_name))
                    elif msg_type == "EXIT":
                        rospy.loginfo("{} left!".format(msg_name))
                    elif msg_type == "SHOUT":
                        # handling incoming information
                        msg_channel = cmds.pop(0)
                        msg_str = cmds.pop(0)
                        self.process_data(msg_str, msg_name)
                except zmq.error.Again:
                    rospy.logerr("ERROR! Again #2")
        n.stop()
示例#51
0
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])
class ZyreToZMQModule:
    """ The ZyreToZMQModule Base Class """
   
    
    def __init__(self,ctx = None,name = "Default",headers=None,groups=None,config_file=None,polling_timeout = 1,sim_time=2):

        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.DEBUG)
        # create the console output logging
        sh = logging.StreamHandler()
        sh.setLevel(logging.INFO)
        # create a logger writing into a log file
        fh = logging.FileHandler(name + ".log")
        fh.setLevel(logging.DEBUG)
        # create formatter and add it to the handlers
        # see https://docs.python.org/2/library/logging.html#logrecord-attributes for what can be logged
        fh.setFormatter(logging.Formatter('Name: %(name)s, ProcessName: %(processName)s, ThreadName: %(threadName)s, Module: %(module)s, FunctionName: %(funcName)s, LineNo: %(lineno)d, Level: %(levelname)s, Msg: %(message)s'))
        #sh.setFormatter(logging.Formatter('Module: %(module)s, FunctionName: %(funcName)s, LineNo: %(lineno)d, Level: %(levelname)s, Msg: %(message)s'))
        sh.setFormatter(logging.Formatter('Name: %(name)s, %(module)s/%(funcName)s[%(levelname)s]: %(message)s (lineno:%(lineno)d)'))
        # add the handlers to logger
        self.logger.addHandler(sh)
        self.logger.addHandler(fh)
        self.logger.propagate = False # don't pass messages to parent loggers

        if not type(ctx) ==  zmq.sugar.context.Context:
            self.logger.warn("Created ZMQ context. Please supply a ZMQ context next time.")
            ctx = zmq.Context()
        self.ctx = ctx
        if not type(name) == str:
            name = "Default"
            self.logger.warn("Please provide a the name as a string. Setting name to default: %s." % name)
        self.name = name
        if not headers:
            self.logger.warn("Please provide a model and other header information.")
            headers = {}
        self.headers = headers
        if not groups:
            groups = ["SHERPA"]
            self.logger.warn("Please provide a list with group names to which it will listen. Will set it to default: %s" %groups)
        self.groups = groups
        if not config_file:
            # will be opened during configuration
            self.logger.error("No config file provided for initial configuration")
            exit()
      
        self.config_file = config_file
        self.config = None
        self.alive = True # used for exiting once the node is stopped
        self.line_controller = None # stores uid of line controller this module is listening to (to avoid several line controllers)
        self.com_timeout = polling_timeout # time_out in msec after which poller returns
        self.sim_time = sim_time # time in msec
        self.inbox = []
        self.outbox = []
             
        # Node setup
        self.node = Pyre(self.name)
        for key in self.headers:
            self.node.set_header(key,self.headers[key])
        for group in self.groups:
            self.node.join(group)
        #self.node.set_verbose()
        self.node.start()
        
        # Socket setup
        self.poller = zmq.Poller()
        self.poller.register(self.node.socket(), zmq.POLLIN)

        port = "12911" 
        self.zmq_socket = self.ctx.socket(zmq.PUB)
        self.zmq_socket.bind("tcp://*:%s" % port)
   

        self.run()


    def run(self):
        """ Running loop of this process:
        [COMMUNICATION]     Check communication channels and parse all messages.
        """
        while self.alive:
            try:
                #[COMMUNICATION]
                self.communication()
                #[LOGGING]
                #self.logging()
                time.sleep(1)
            except (KeyboardInterrupt, SystemExit):
                break
        self.node.stop()


    def communication(self):
        """ This function handles the communication """

        # Check if communication is ready
        if not self.poller:
            self.logger.warn("No communication channels yet.")
        # Process input
        items = dict(self.poller.poll(self.com_timeout))
        # Get input from Pyre socket and put it in inbox which is processed in the following steps
        #logger.debug("Start processing incoming messages")
        if self.node.socket() in items and items[self.node.socket()] == zmq.POLLIN: 
            self.logger.info("Received %d msgs." % len(items))
            #print "msg arrived. inbox len %d" % len(self.inbox)
            msg_frame = self.node.recv()
            msg_type = msg_frame.pop(0)
            peer_uid = uuid.UUID(bytes=msg_frame.pop(0))
            peer_name = msg_frame.pop(0)   
            self.logger.info("Msg type: %s" % msg_type)         
            self.logger.info("Sender: %s" % peer_name)   
            # For shout and whisper take message payload and put it into inbox assuming it is correct
            # For the other zyre msgs create a JSON obj and put that into inbox
            # TODO: add validation
            if msg_type == "SHOUT":
                group = msg_frame.pop(0)
                msg = json.loads(msg_frame.pop(0))
                msg["sender_UUID"] = peer_uid
                msg["sender_name"] = peer_name
#                self.inbox.append(msg)
                self.outbox.append(msg)
            elif msg_type == "WHISPER":
                msg = json.loads(msg_frame.pop(0))
                msg["sender_UUID"] = peer_uid
                msg["sender_name"] = peer_name
                self.inbox.append(msg)        
            # don't care about join and leave messages; if necessary, split to have separate events               
#             elif msg_type == "LEAVE" or msg_type == "JOIN":
#                 group = msg_frame.pop(0)
#                 event = json.dumps({"metamodel": "http://www.sherpa-project.eu/examples/sherpa_msgs",
#                                     "model": "http://www.sherpa-project.eu/examples/sherpa_msgs/zyre_events",
#                                     "type": "leave/join",
#                                     "sender_UUID": peer_uid,
#                                     "sender_name": peer_name,
#                                     "payload": {}
#                                     })
#                 self.inbox.append(event)
            elif msg_type == "ENTER":
                headers = json.loads(msg_frame.pop(0))
                event = {"metamodel": "http://www.sherpa-project.eu/examples/sherpa_msgs",
                         "model": "http://www.sherpa-project.eu/examples/sherpa_msgs/zyre_events",
                         "type": "enter",
                         "sender_UUID": peer_uid,
                         "sender_name": peer_name,
                         "payload": {"header": headers}
                         }
                self.inbox.append(event)
            elif msg_type == "EXIT":
                event = {"metamodel": "http://www.sherpa-project.eu/examples/sherpa_msgs",
                         "model": "http://www.sherpa-project.eu/examples/sherpa_msgs/zyre_events",
                         "type": "exit",
                         "sender_UUID": peer_uid,
                         "sender_name": peer_name,
                         "payload": {}
                         }
                self.inbox.append(event)
        # Process output and send all msgs there until it is empty, but only if a line controller is connected.
        if self.outbox: #only do if there really is something in the outbox
            #if self.lcsm.sm.curr_state._name == "Idle" or self.lcsm.sm.curr_state._name == "Busy":
            if true:
                self.logger.info("Start processing messages in outbox. Number of msgs in outbox: %d" % len(self.outbox))
                while self.outbox:
                    # since we assume all msgs conform to the sherpa_msgs JSON model, simply shout them out
                    # TODO: add validation
                    msg = self.outbox.pop()
                    if type(msg) == dict:
                        self.logger.info("outbox msg type: " + msg["type"])
                        self.node.shout("SHERPA", json.dumps(msg))
                        
                        #WM message
                        
                        msg_wm_update = {
                          "@worldmodeltype": "RSGUpdate",
                          "operation": "CREATE",
                          "node": {
                            "@graphtype": "Group",
                            "id": "ff483c43-4a36-4197-be49-de829cdd66c8", 
                            "attributes": [
                                  {"key": "name", "value": "Task Specification Tree"},
                                  {"key": "tst:envtst", "value": msg },
                            ],
                          },
                          "parentId": "e379121f-06c6-4e21-ae9d-ae78ec1986a1",
                        }
                  
                        print ("===")
                        print (json.dumps(msg_wm_update))
                        self.zmq_socket.send_string(json.dumps(msg_wm_update)) 

                    else:
                        self.logger.warn("Message is not a dict! Serialization is done here! Msg: \n" + str(msg))
            else:
                self.logger.info("Can't send messages in outbox. Module not ready.")
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()
示例#54
0
def rethinkdb_writer(ctx, pipe):

    # Database setup
    with open('../configuration.json') as data_file:
        configuration = json.load(data_file)

    group_name = configuration['zyreMediator']['group']

    n = Pyre(configuration['zyreMediator']['name'])
    n.set_interface('usb0')
    n.set_header('TYPE', configuration['zyreMediator']['type'])
    n.join(group_name)
    n.start()

    # Zyre setup
    poller = zmq.Poller()
    poller.register(pipe, zmq.POLLIN)
    poller.register(n.inbox, zmq.POLLIN)

    database_configuration = configuration['database']['mongoDB']
    mongo_connection = MongoClient(database_configuration['host'], database_configuration['port'])

    meteor = mongo_connection['meteor']

    # Add this module to the database
    meteor['modules'].insert([{
        '_id': str(n.uuid()),
        'name': n.name(),
        'type': configuration['zyreMediator']['type'],
        'parent': None
    }])

    ready_message = {
        'type': 'state',
        'senderId': str(n.uuid()),
        'payload': 2
    }

    def logMessage(message_to_log):
        message_to_log['timestamp'] = datetime.datetime.utcnow()
        meteor['events'].insert_one(message_to_log)
        del message_to_log['timestamp']
        del message_to_log['_id']

    n.shout(group_name, json.dumps(ready_message))
    logMessage(ready_message)

    module_name_to_uid_map = {}

    while True:
        items = dict(poller.poll(10))

        if pipe in items and items[pipe] == zmq.POLLIN:
            message = pipe.recv()
            # message to quit
            if message.decode('utf-8') == '$$STOP':
                break

        if n.inbox in items and items[n.inbox] == zmq.POLLIN:

            msg_frame = n.recv()
            msg_type = msg_frame.pop(0)
            peer_uid = uuid.UUID(bytes=msg_frame.pop(0))
            peer_name = msg_frame.pop(0)
            print('NODE_MSG TYPE: %s' % msg_type)
            print('NODE_MSG PEER: %s' % str(peer_uid))
            print('NODE_MSG NAME: %s' % peer_name)

            if msg_type.decode('utf-8') == 'ENTER':

                headers = json.loads(msg_frame.pop(0))

                try:
                    module_type = headers['type']
                except KeyError:
                    print("Your header doesn't contain your type of module")
                    module_type = 'unknown'

                try:
                    parent_module_id = headers['parentId']
                except KeyError:
                    print("The header doesn't contain the module's parent id")
                    parent_module_id = None

                # creates an entry with all known information about the robot
                # in the database if the robot is not in the database
                meteor['modules'].insert_one({
                    '_id': str(peer_uid),
                    'name': peer_name,
                    'type': module_type,
                    'parent': parent_module_id
                })

                module_name_to_uid_map[peer_name] = str(peer_uid)

            elif msg_type.decode('utf-8') == 'EXIT':
                meteor['modules'].remove({'_id': str(peer_uid)})

            elif msg_type.decode('utf-8') == 'SHOUT':

                # write message to database
                group = msg_frame.pop(0)
                try:
                    data = json.loads(msg_frame[0])
                except:
                    data = {}
                    print 'Invalid JSON string'

                # print data

                data['senderId'] = str(peer_uid)
                logMessage(data)

            elif msg_type.decode('utf-8') == 'WHISPER':
                # write message to database
                try:
                    data = json.loads(msg_frame[0])
                except:
                    print 'Invalid JSON string'

                logMessage(data)

    meteor['modules'].remove({'_id': str(n.uuid())})
    n.stop()
    def __init__(self,ctx = None,name = "Default",headers=None,groups=None,config_file=None,polling_timeout = 1,sim_time=2):

        self.logger = logging.getLogger(name)
        self.logger.setLevel(logging.DEBUG)
        # create the console output logging
        sh = logging.StreamHandler()
        sh.setLevel(logging.INFO)
        # create a logger writing into a log file
        fh = logging.FileHandler(name + ".log")
        fh.setLevel(logging.DEBUG)
        # create formatter and add it to the handlers
        # see https://docs.python.org/2/library/logging.html#logrecord-attributes for what can be logged
        fh.setFormatter(logging.Formatter('Name: %(name)s, ProcessName: %(processName)s, ThreadName: %(threadName)s, Module: %(module)s, FunctionName: %(funcName)s, LineNo: %(lineno)d, Level: %(levelname)s, Msg: %(message)s'))
        #sh.setFormatter(logging.Formatter('Module: %(module)s, FunctionName: %(funcName)s, LineNo: %(lineno)d, Level: %(levelname)s, Msg: %(message)s'))
        sh.setFormatter(logging.Formatter('Name: %(name)s, %(module)s/%(funcName)s[%(levelname)s]: %(message)s (lineno:%(lineno)d)'))
        # add the handlers to logger
        self.logger.addHandler(sh)
        self.logger.addHandler(fh)
        self.logger.propagate = False # don't pass messages to parent loggers

        if not type(ctx) ==  zmq.sugar.context.Context:
            self.logger.warn("Created ZMQ context. Please supply a ZMQ context next time.")
            ctx = zmq.Context()
        self.ctx = ctx
        if not type(name) == str:
            name = "Default"
            self.logger.warn("Please provide a the name as a string. Setting name to default: %s." % name)
        self.name = name
        if not headers:
            self.logger.warn("Please provide a model and other header information.")
            headers = {}
        self.headers = headers
        if not groups:
            groups = ["SHERPA"]
            self.logger.warn("Please provide a list with group names to which it will listen. Will set it to default: %s" %groups)
        self.groups = groups
        if not config_file:
            # will be opened during configuration
            self.logger.error("No config file provided for initial configuration")
            exit()
      
        self.config_file = config_file
        self.config = None
        self.alive = True # used for exiting once the node is stopped
        self.line_controller = None # stores uid of line controller this module is listening to (to avoid several line controllers)
        self.com_timeout = polling_timeout # time_out in msec after which poller returns
        self.sim_time = sim_time # time in msec
        self.inbox = []
        self.outbox = []
             
        # Node setup
        self.node = Pyre(self.name)
        for key in self.headers:
            self.node.set_header(key,self.headers[key])
        for group in self.groups:
            self.node.join(group)
        #self.node.set_verbose()
        self.node.start()
        
        # Socket setup
        self.poller = zmq.Poller()
        self.poller.register(self.node.socket(), zmq.POLLIN)

        port = "12911" 
        self.zmq_socket = self.ctx.socket(zmq.PUB)
        self.zmq_socket.bind("tcp://*:%s" % port)
   

        self.run()