def del_interrupt_callback(self, gpio_id): """ Delete all interrupt callbacks from a certain gpio """ debug("- removing interrupts on gpio %s" % gpio_id) gpio_id = _GPIO.channel_to_gpio(gpio_id) fileno = self._map_gpioid_to_fileno[gpio_id] # 1. Remove from epoll self._epoll.unregister(fileno) # 2. Cache the file f = self._map_fileno_to_file[fileno] # 3. Remove from maps del self._map_fileno_to_file[fileno] del self._map_fileno_to_gpioid[fileno] del self._map_fileno_to_options[fileno] del self._map_gpioid_to_fileno[gpio_id] del self._map_gpioid_to_callbacks[gpio_id] # 4. Close file last in case of IOError f.close()
def add_interrupt_callback(self, gpio_id, callback, edge='both', pull_up_down=_GPIO.PUD_OFF, threaded_callback=False, debounce_timeout_ms=None): """ Add a callback to be executed when the value on 'gpio_id' changes to the edge specified via the 'edge' parameter (default='both'). `pull_up_down` can be set to `RPIO.PUD_UP`, `RPIO.PUD_DOWN`, and `RPIO.PUD_OFF`. If `threaded_callback` is True, the callback will be started inside a Thread. """ gpio_id = _GPIO.channel_to_gpio(gpio_id) debug("Adding callback for GPIO %s" % gpio_id) if not edge in ["falling", "rising", "both", "none"]: raise AttributeError("'%s' is not a valid edge." % edge) if not pull_up_down in [_GPIO.PUD_UP, _GPIO.PUD_DOWN, _GPIO.PUD_OFF]: raise AttributeError("'%s' is not a valid pull_up_down." % edge) # Make sure the gpio_id is valid if not gpio_id in (RPIO.GPIO_LIST_R1 if _GPIO.RPI_REVISION == 1 else \ RPIO.GPIO_LIST_R2): raise AttributeError("GPIO %s is not a valid gpio-id." % gpio_id) # Require INPUT pin setup; and set the correct PULL_UPDN if RPIO.gpio_function(int(gpio_id)) == RPIO.IN: RPIO.set_pullupdn(gpio_id, pull_up_down) else: debug("- changing gpio function from %s to INPUT" % \ (GPIO_FUNCTIONS[RPIO.gpio_function(int(gpio_id))])) RPIO.setup(gpio_id, RPIO.IN, pull_up_down) # Prepare the callback (wrap in Thread if needed) cb = callback if not threaded_callback else \ partial(_threaded_callback, callback) # Prepare the /sys/class path of this gpio path_gpio = "%sgpio%s/" % (_SYS_GPIO_ROOT, gpio_id) # If initial callback for this GPIO then set everything up. Else make # sure the edge detection is the same. if gpio_id in self._map_gpioid_to_callbacks: with open(path_gpio + "edge", "r") as f: e = f.read().strip() if e != edge: raise AttributeError(("Cannot add callback for gpio %s:" " edge detection '%s' not compatible with existing" " edge detection '%s'.") % (gpio_id, edge, e)) # Check whether edge is the same, else throw Exception debug("- kernel interface already setup for GPIO %s" % gpio_id) self._map_gpioid_to_callbacks[gpio_id].append(cb) else: # If kernel interface already exists unexport first for clean setup if os.path.exists(path_gpio): if self._show_warnings: warn("Kernel interface for GPIO %s already exists." % \ gpio_id) debug("- unexporting kernel interface for GPIO %s" % gpio_id) with open(_SYS_GPIO_ROOT + "unexport", "w") as f: f.write("%s" % gpio_id) time.sleep(0.1) # Export kernel interface /sys/class/gpio/gpioN with open(_SYS_GPIO_ROOT + "export", "w") as f: f.write("%s" % gpio_id) self._gpio_kernel_interfaces_created.append(gpio_id) debug("- kernel interface exported for GPIO %s" % gpio_id) # Configure gpio as input with open(path_gpio + "direction", "w") as f: f.write("in") # Configure gpio edge detection with open(path_gpio + "edge", "w") as f: f.write(edge) debug(("- kernel interface configured for GPIO %s " "(edge='%s', pullupdn=%s)") % (gpio_id, edge, \ _PULL_UPDN[pull_up_down])) # Open the gpio value stream and read the initial value f = open(path_gpio + "value", 'r') val_initial = f.read().strip() debug("- inital gpio value: %s" % val_initial) f.seek(0) # Add callback info to the mapping dictionaries self._map_fileno_to_file[f.fileno()] = f self._map_fileno_to_gpioid[f.fileno()] = gpio_id self._map_fileno_to_options[f.fileno()] = { "debounce_timeout_s": debounce_timeout_ms / 1000.0 if \ debounce_timeout_ms else 0, "interrupt_last": 0, "edge": edge } self._map_gpioid_to_fileno[gpio_id] = f.fileno() self._map_gpioid_to_callbacks[gpio_id] = [cb] # Add to epoll self._epoll.register(f.fileno(), select.EPOLLPRI | select.EPOLLERR)
def add_interrupt_callback(self, gpio_id, callback, edge='both', pull_up_down=_GPIO.PUD_OFF, threaded_callback=False, debounce_timeout_ms=None): """ Add a callback to be executed when the value on 'gpio_id' changes to the edge specified via the 'edge' parameter (default='both'). `pull_up_down` can be set to `RPIO.PUD_UP`, `RPIO.PUD_DOWN`, and `RPIO.PUD_OFF`. If `threaded_callback` is True, the callback will be started inside a Thread. """ gpio_id = _GPIO.channel_to_gpio(gpio_id) debug("Adding callback for GPIO %s" % gpio_id) if not edge in ["falling", "rising", "both", "none"]: raise AttributeError("'%s' is not a valid edge." % edge) if not pull_up_down in [_GPIO.PUD_UP, _GPIO.PUD_DOWN, _GPIO.PUD_OFF]: raise AttributeError("'%s' is not a valid pull_up_down." % edge) # Make sure the gpio_id is valid if not gpio_id in (RPIO.GPIO_LIST_R1 if _GPIO.RPI_REVISION == 1 else \ RPIO.GPIO_LIST_R2): raise AttributeError("GPIO %s is not a valid gpio-id." % gpio_id) # Require INPUT pin setup; and set the correct PULL_UPDN if RPIO.gpio_function(int(gpio_id)) == RPIO.IN: RPIO.set_pullupdn(gpio_id, pull_up_down) else: debug("- changing gpio function from %s to INPUT" % \ (GPIO_FUNCTIONS[RPIO.gpio_function(int(gpio_id))])) RPIO.setup(gpio_id, RPIO.IN, pull_up_down) # Prepare the callback (wrap in Thread if needed) cb = callback if not threaded_callback else \ partial(_threaded_callback, callback) # Prepare the /sys/class path of this gpio path_gpio = "%sgpio%s/" % (_SYS_GPIO_ROOT, gpio_id) # If initial callback for this GPIO then set everything up. Else make # sure the edge detection is the same. if gpio_id in self._map_gpioid_to_callbacks: with open(path_gpio + "edge", "r") as f: e = f.read().strip() if e != edge: raise AttributeError( ("Cannot add callback for gpio %s:" " edge detection '%s' not compatible with existing" " edge detection '%s'.") % (gpio_id, edge, e)) # Check whether edge is the same, else throw Exception debug("- kernel interface already setup for GPIO %s" % gpio_id) self._map_gpioid_to_callbacks[gpio_id].append(cb) else: # If kernel interface already exists unexport first for clean setup if os.path.exists(path_gpio): if self._show_warnings: warn("Kernel interface for GPIO %s already exists." % \ gpio_id) debug("- unexporting kernel interface for GPIO %s" % gpio_id) with open(_SYS_GPIO_ROOT + "unexport", "w") as f: f.write("%s" % gpio_id) time.sleep(0.1) # Export kernel interface /sys/class/gpio/gpioN with open(_SYS_GPIO_ROOT + "export", "w") as f: f.write("%s" % gpio_id) self._gpio_kernel_interfaces_created.append(gpio_id) debug("- kernel interface exported for GPIO %s" % gpio_id) # Configure gpio as input with open(path_gpio + "direction", "w") as f: f.write("in") # Configure gpio edge detection with open(path_gpio + "edge", "w") as f: f.write(edge) debug(("- kernel interface configured for GPIO %s " "(edge='%s', pullupdn=%s)") % (gpio_id, edge, \ _PULL_UPDN[pull_up_down])) # Open the gpio value stream and read the initial value f = open(path_gpio + "value", 'r') val_initial = f.read().strip() debug("- inital gpio value: %s" % val_initial) f.seek(0) # Add callback info to the mapping dictionaries self._map_fileno_to_file[f.fileno()] = f self._map_fileno_to_gpioid[f.fileno()] = gpio_id self._map_fileno_to_options[f.fileno()] = { "debounce_timeout_s": debounce_timeout_ms / 1000.0 if \ debounce_timeout_ms else 0, "interrupt_last": 0, "edge": edge } self._map_gpioid_to_fileno[gpio_id] = f.fileno() self._map_gpioid_to_callbacks[gpio_id] = [cb] # Add to epoll self._epoll.register(f.fileno(), select.EPOLLPRI | select.EPOLLERR)