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 _thread_loop(self,context,pipe): # Pyre helper functions 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 def shutdown_group_member(node): node.leave(self.active_group) node.stop() # setup sockets local_in = Msg_Receiver(context, self.g_pool.ipc_sub_url, topics=('remote_notify.',)) local_out = Msg_Dispatcher(context, self.g_pool.ipc_push_url) group_member = setup_group_member() # register sockets for polling poller = zmq.Poller() poller.register(pipe,zmq.POLLIN) poller.register(local_in.socket,zmq.POLLIN) poller.register(group_member.socket(),zmq.POLLIN) logger.info('Pupil Groups started.') # Poll loop while True: # Wait for next readable item readable = dict(poller.poll()) # shout or whisper marked notifications if local_in.socket in readable: topic, notification = local_in.recv() remote_key = 'remote_notify' if notification[remote_key] == 'all': del notification[remote_key] serialized = serializer.dumps(notification) group_member.shout(self.active_group,serialized) else: peer_uuid_bytes = notification[remote_key] del notification[remote_key] serialized = serializer.dumps(notification) peer_uuid = uuid.UUID(bytes=peer_uuid_bytes) group_member.whisper(peer_uuid,serialized) if group_member.socket() in readable: event = PyreEvent(group_member) if event.msg: for msg in event.msg: try: # try to unpack data notification = serializer.loads(msg) # test if dictionary and if `subject` key is present notification['subject'] # add peer information notification['groups.peer'] = { 'uuid_bytes': event.peer_uuid_bytes, 'name': event.peer_name, 'arrival_timestamp': self.g_pool.get_timestamp(), 'type': event.type } local_out.notify(notification) except Exception as e: logger.info('Dropped garbage data by peer %s (%s)'%(event.peer_name, event.peer_uuid)) elif event.type == 'JOIN' and event.group == self.active_group: local_out.notify({ 'subject': 'groups.member_joined', 'name': event.peer_name, 'uuid_bytes': event.peer_uuid_bytes }) elif (event.type == 'LEAVE' and \ event.group == self.active_group) or \ event.type == 'EXIT': local_out.notify({ 'subject': 'groups.member_left', 'name': event.peer_name, 'uuid_bytes': event.peer_uuid_bytes }) if pipe in readable: command = pipe.recv() if command == '$RESTART': # Restart group_member node to change name poller.unregister(group_member.socket()) shutdown_group_member(group_member) group_member = setup_group_member() poller.register(group_member.socket(),zmq.POLLIN) elif command == '$TERM': break del local_in del local_out shutdown_group_member(group_member) self.thread_pipe = None
def _thread_loop(self, context, pipe): # Pyre helper functions 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 def shutdown_group_member(node): node.leave(self.active_group) node.stop() # setup sockets local_in = Msg_Receiver(context, self.g_pool.ipc_sub_url, topics=("remote_notify.", )) local_out = Msg_Dispatcher(context, self.g_pool.ipc_push_url) group_member = setup_group_member() # register sockets for polling poller = zmq.Poller() poller.register(pipe, zmq.POLLIN) poller.register(local_in.socket, zmq.POLLIN) poller.register(group_member.socket(), zmq.POLLIN) logger.info("Pupil Groups started.") # Poll loop while True: # Wait for next readable item readable = dict(poller.poll()) # shout or whisper marked notifications if local_in.socket in readable: topic, notification = local_in.recv() remote_key = "remote_notify" if notification[remote_key] == "all": del notification[remote_key] serialized = serializer.dumps(notification) group_member.shout(self.active_group, serialized) else: peer_uuid_bytes = notification[remote_key] del notification[remote_key] serialized = serializer.dumps(notification) peer_uuid = uuid.UUID(bytes=peer_uuid_bytes) group_member.whisper(peer_uuid, serialized) if group_member.socket() in readable: event = PyreEvent(group_member) if event.msg: for msg in event.msg: try: # try to unpack data notification = serializer.loads(msg, encoding="utf-8") # test if dictionary and if `subject` key is present notification["subject"] # add peer information notification["groups.peer"] = { "uuid_bytes": event.peer_uuid_bytes, "name": event.peer_name, "arrival_timestamp": self.g_pool.get_timestamp(), "type": event.type, } local_out.notify(notification) except Exception: logger.info( "Dropped garbage data by peer {} ({})".format( event.peer_name, event.peer_uuid)) elif event.type == "JOIN" and event.group == self.active_group: local_out.notify({ "subject": "groups.member_joined", "name": event.peer_name, "uuid_bytes": event.peer_uuid_bytes, }) elif (event.type == "LEAVE" and event.group == self.active_group) or event.type == "EXIT": local_out.notify({ "subject": "groups.member_left", "name": event.peer_name, "uuid_bytes": event.peer_uuid_bytes, }) if pipe in readable: command = pipe.recv_string() if command == "$RESTART": # Restart group_member node to change name poller.unregister(group_member.socket()) shutdown_group_member(group_member) group_member = setup_group_member() poller.register(group_member.socket(), zmq.POLLIN) elif command == "$TERM": break del local_in del local_out shutdown_group_member(group_member) self.thread_pipe = None
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())