コード例 #1
0
ファイル: uvc-ndsi-bridge-host.py プロジェクト: papr/pyndsi
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])
コード例 #2
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])
コード例 #3
0
ファイル: uvc-ndsi-bridge-host.py プロジェクト: vedb/pyndsi
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])