Beispiel #1
0
    def _notifications_handler(self, n):
        assert self.receiver
        # if _log.isEnabledFor(_DEBUG):
        # 	_log.debug("%s: handling %s", self.receiver, n)
        if n.devnumber == 0xFF:
            # a receiver notification
            _notifications.process(self.receiver, n)
            return

        # a device notification
        assert 0 < n.devnumber <= self.receiver.max_devices
        already_known = n.devnumber in self.receiver

        # FIXME: hacky fix for kernel/hardware race condition
        # If the device was just turned on or woken up from sleep, it may not
        # be ready to receive commands. The "payload" bit of the wireless
        # status notification seems to tell us this. If this is the case, we
        # must wait a short amount of time to avoid causing a broken pipe
        # error.
        device_ready = not bool(ord(n.data[0:1]) & 0x80) or n.sub_id != 0x41
        if not device_ready:
            time.sleep(0.01)

        if n.sub_id == 0x40 and not already_known:
            return  # disconnecting something that is not known - nothing to do

        if n.sub_id == 0x41 and not already_known:
            dev = self.receiver.register_new_device(n.devnumber, n)
        else:
            dev = self.receiver[n.devnumber]

        if not dev:
            _log.warn("%s: received %s for invalid device %d: %r",
                      self.receiver, n, n.devnumber, dev)
            return

        # Apply settings every time the device connects
        if n.sub_id == 0x41:
            if _log.isEnabledFor(_INFO):
                _log.info("%s triggered new device %s (%s)", n, dev, dev.kind)
            # If there are saved configs, bring the device's settings up-to-date.
            # They will be applied when the device is marked as online.
            configuration.attach_to(dev)
            _status.attach_to(dev, self._status_changed)
            # the receiver changed status as well
            self._status_changed(self.receiver)

        assert dev
        assert dev.status is not None
        _notifications.process(dev, n)
        if self.receiver.status.lock_open and not already_known:
            # this should be the first notification after a device was paired
            assert n.sub_id == 0x41 and n.address == 0x04
            if _log.isEnabledFor(_INFO):
                _log.info("%s: pairing detected new device", self.receiver)
            self.receiver.status.new_device = dev
        elif dev.online is None:
            dev.ping()
Beispiel #2
0
	def __init__(self, receiver, status_changed_callback):
		super(ReceiverListener, self).__init__(receiver, self._notifications_handler)
		# no reason to enable polling yet
		# self.tick_period = _POLL_TICK
		# self._last_tick = 0

		assert status_changed_callback
		self.status_changed_callback = status_changed_callback
		_status.attach_to(receiver, self._status_changed)
Beispiel #3
0
    def __init__(self, receiver, status_changed_callback):
        super(ReceiverListener, self).__init__(receiver, self._notifications_handler)
        # no reason to enable polling yet
        # self.tick_period = _POLL_TICK
        # self._last_tick = 0

        assert status_changed_callback
        self.status_changed_callback = status_changed_callback
        _status.attach_to(receiver, self._status_changed)
Beispiel #4
0
	def _notifications_handler(self, n):
		assert self.receiver
		# if _log.isEnabledFor(_DEBUG):
		# 	_log.debug("%s: handling %s", self.receiver, n)
		if n.devnumber == 0xFF:
			# a receiver notification
			_notifications.process(self.receiver, n)
			return

		# a device notification
		assert 0 < n.devnumber <= self.receiver.max_devices
		already_known = n.devnumber in self.receiver

		# FIXME: hacky fix for kernel/hardware race condition
		# If the device was just turned on or woken up from sleep, it may not
		# be ready to receive commands. The "payload" bit of the wireless
		# status notification seems to tell us this. If this is the case, we
		# must wait a short amount of time to avoid causing a broken pipe
		# error.
		device_ready = not bool(ord(n.data[0:1]) & 0x80) or n.sub_id != 0x41
		if not device_ready:
			time.sleep(0.01)

		if n.sub_id == 0x41 and not already_known:
			dev = self.receiver.register_new_device(n.devnumber, n)
		else:
			dev = self.receiver[n.devnumber]

		if not dev:
			_log.warn("%s: received %s for invalid device %d: %r", self.receiver, n, n.devnumber, dev)
			return

		# Apply settings every time the device connects
		if n.sub_id == 0x41:
			if _log.isEnabledFor(_INFO):
				_log.info("%s triggered new device %s (%s)", n, dev, dev.kind)
			# If there are saved configs, bring the device's settings up-to-date.
			# They will be applied when the device is marked as online.
			configuration.attach_to(dev)
			_status.attach_to(dev, self._status_changed)
			# the receiver changed status as well
			self._status_changed(self.receiver)

		assert dev
		assert dev.status is not None
		_notifications.process(dev, n)
		if self.receiver.status.lock_open and not already_known:
			# this should be the first notification after a device was paired
			assert n.sub_id == 0x41 and n.address == 0x04
			if _log.isEnabledFor(_INFO):
				_log.info("%s: pairing detected new device", self.receiver)
			self.receiver.status.new_device = dev
		elif dev.online is None:
				dev.ping()
Beispiel #5
0
    def __init__(self, receiver, status_changed_callback):
        super().__init__(receiver, self._notifications_handler)
        # no reason to enable polling yet
        # self.tick_period = _POLL_TICK
        # self._last_tick = 0

        assert status_changed_callback
        self.status_changed_callback = status_changed_callback
        _status.attach_to(receiver, self._status_changed)
        if receiver.isDevice:  # ping (wired) devices to see if they are really online
            if receiver.ping():
                receiver.status.changed(True, reason='initialization')
Beispiel #6
0
    def _notifications_handler(self, n):
        assert self.receiver
        # if _log.isEnabledFor(_DEBUG):
        # 	_log.debug("%s: handling %s", self.receiver, n)
        if n.devnumber == 0xFF:
            # a receiver notification
            _notifications.process(self.receiver, n)
            return

        # a device notification
        assert 0 < n.devnumber <= self.receiver.max_devices
        already_known = n.devnumber in self.receiver

        # 0x41 is a connection notice, not a pairing notice
        # so the device may have been previously paired
        if n.sub_id == 0x41 and not already_known:
            dev = self.receiver.register_new_device(n.devnumber, n)
        else:
            dev = self.receiver[n.devnumber]

        if not dev:
            _log.warn("%s: received %s for invalid device %d: %r",
                      self.receiver, n, n.devnumber, dev)
            return

        # Apply settings every time the device connects
        if n.sub_id == 0x41:
            if _log.isEnabledFor(_INFO):
                _log.info("%s triggered new device %s (%s)", n, dev, dev.kind)
            # If there are saved configs, bring the device's settings up-to-date.
            # They will be applied when the device is marked as online.
            configuration.attach_to(dev)
            _status.attach_to(dev, self._status_changed)
            # the receiver changed status as well
            self._status_changed(self.receiver)

        assert dev
        assert dev.status is not None
        _notifications.process(dev, n)
        if self.receiver.status.lock_open and not already_known:
            # this should be the first notification after a device was paired
            assert n.sub_id == 0x41 and n.address == 0x04
            if _log.isEnabledFor(_INFO):
                _log.info("%s: pairing detected new device", self.receiver)
            self.receiver.status.new_device = dev
        elif dev.online is None:
            dev.ping()
Beispiel #7
0
	def _notifications_handler(self, n):
		assert self.receiver
		# if _log.isEnabledFor(_DEBUG):
		# 	_log.debug("%s: handling %s", self.receiver, n)
		if n.devnumber == 0xFF:
			# a receiver notification
			_notifications.process(self.receiver, n)
			return

		# a device notification
		assert n.devnumber > 0 and n.devnumber <= self.receiver.max_devices
		already_known = n.devnumber in self.receiver

		if n.sub_id == 0x41:
			already_known = False
			dev = self.receiver.register_new_device(n.devnumber, n)
		else:
			dev = self.receiver[n.devnumber]

		if not dev:
			_log.warn("%s: received %s for invalid device %d: %r", self.receiver, n, n.devnumber, dev)
			return

		if not already_known:
			if _log.isEnabledFor(_INFO):
				_log.info("%s triggered new device %s (%s)", n, dev, dev.kind)
			# If there are saved configs, bring the device's settings up-to-date.
			# They will be applied when the device is marked as online.
			configuration.attach_to(dev)
			_status.attach_to(dev, self._status_changed)
			# the receiver changed status as well
			self._status_changed(self.receiver)

		assert dev
		assert dev.status is not None
		_notifications.process(dev, n)
		if self.receiver.status.lock_open and not already_known:
			# this should be the first notification after a device was paired
			assert n.sub_id == 0x41 and n.address == 0x04
			if _log.isEnabledFor(_INFO):
				_log.info("%s: pairing detected new device", self.receiver)
			self.receiver.status.new_device = dev
		elif dev:
			if dev.online is None:
				dev.ping()
Beispiel #8
0
    def _notifications_handler(self, n):
        assert self.receiver
        # if _log.isEnabledFor(_DEBUG):
        #     _log.debug("%s: handling %s", self.receiver, n)
        if n.devnumber == 0xFF:
            # a receiver notification
            _notifications.process(self.receiver, n)
            return

        # a notification that came in to the device listener - strange, but nothing needs to be done here
        if self.receiver.isDevice:
            if _log.isEnabledFor(_DEBUG):
                _log.debug('Notification %s via device %s being ignored.', n,
                           self.receiver)
            return

        # DJ pairing notification - ignore - hid++ 1.0 pairing notification is all that is needed
        if n.sub_id == 0x41 and n.report_id == _base.DJ_MESSAGE_ID:
            if _log.isEnabledFor(_INFO):
                _log.info('ignoring DJ pairing notification %s', n)
            return

        # a device notification
        if not (0 < n.devnumber <= self.receiver.max_devices):
            if _log.isEnabledFor(_WARNING):
                _log.warning(
                    'Unexpected device number (%s) in notification %s.',
                    n.devnumber, n)
            return
        already_known = n.devnumber in self.receiver

        # FIXME: hacky fix for kernel/hardware race condition
        # If the device was just turned on or woken up from sleep, it may not
        # be ready to receive commands. The "payload" bit of the wireless
        # status notification seems to tell us this. If this is the case, we
        # must wait a short amount of time to avoid causing a broken pipe
        # error.
        device_ready = not bool(ord(n.data[0:1]) & 0x80) or n.sub_id != 0x41
        if not device_ready:
            time.sleep(0.01)

        if n.sub_id == 0x40 and not already_known:
            return  # disconnecting something that is not known - nothing to do

        if n.sub_id == 0x41:
            if not already_known:
                if n.address == 0x0A and not self.receiver.receiver_kind == 'bolt':
                    # some Nanos send a notification even if no new pairing - check that there really is a device there
                    if self.receiver.read_register(
                            _R.receiver_info,
                            _IR.pairing_information + n.devnumber - 1) is None:
                        return
                dev = self.receiver.register_new_device(n.devnumber, n)
            elif self.receiver.status.lock_open and self.receiver.re_pairs and not ord(
                    n.data[0:1]) & 0x40:
                dev = self.receiver[n.devnumber]
                del self.receiver[
                    n.
                    devnumber]  # get rid of information on device re-paired away
                self._status_changed(
                    dev)  # signal that this device has changed
                dev = self.receiver.register_new_device(n.devnumber, n)
                self.receiver.status.new_device = self.receiver[n.devnumber]
            else:
                dev = self.receiver[n.devnumber]
        else:
            dev = self.receiver[n.devnumber]

        if not dev:
            _log.warn('%s: received %s for invalid device %d: %r',
                      self.receiver, n, n.devnumber, dev)
            return

        # Apply settings every time the device connects
        if n.sub_id == 0x41:
            if _log.isEnabledFor(_INFO):
                _log.info('connection %s for %s (%s)', n, dev, dev.kind)
            # If there are saved configs, bring the device's settings up-to-date.
            # They will be applied when the device is marked as online.
            configuration.attach_to(dev)
            _status.attach_to(dev, self._status_changed)
            # the receiver changed status as well
            self._status_changed(self.receiver)

        if not hasattr(dev, 'status') or dev.status is None:
            # notification before device status set up - don't process it
            _log.warn('%s before device %s has status', n, dev)
        else:
            _notifications.process(dev, n)

        if self.receiver.status.lock_open and not already_known:
            # this should be the first notification after a device was paired
            assert n.sub_id == 0x41, 'first notification was not a connection notification'
            if _log.isEnabledFor(_INFO):
                _log.info('%s: pairing detected new device', self.receiver)
            self.receiver.status.new_device = dev
        elif dev.online is None:
            dev.ping()