Skip to main content

Python Blink(1) library

Official Python library for blink(1) USB RGB LED notification devices https://blink1.thingm.com/

CI PyPI

About this library

Features of this library:

  • Test suite that runs without a blink(1) attached, plus hardware tests
  • Python 3.9+
  • Automatic installation via Python Package Index
  • High level control over the blink(1)
  • Type hints throughout, with a py.typed marker so they reach your type checker
  • Single implementation with cython-hidapi USB HID API (PyUSB cannot access HID devices on all OSes)

This library lives at https://github.com/todbot/blink1-python

Changes are recorded in CHANGELOG.md. If you are upgrading from 0.4.0, read its "Changed" section first: 1.0.0 has five behavior changes, including colors outside 0-255 now raising InvalidColor, and a corrected value for the fluorescent white point.

Originally written by @salimfadhley, at https://github.com/salimfadhley/blink1/tree/master/python/pypi. Moved to this repository and rewritten for cython-hidapi by @todbot.

Installation

Use the pip utility to fetch the latest release of this package and any additional components required in a single step:

  pip install blink1

Example Code and Installed scripts

Two command-line scripts blink1-shine and blink1-flash are installed when this library is installed.

blink1-shine sets the blink(1) to a specific steady color:

  blink1-shine --color red
  blink1-shine --color '#ff00ff' --fade 1.5
  blink1-shine --switch-off          # set the color, then turn it off on exit
  blink1-shine --serial 20002345     # pick one of several blink(1)s
  blink1-shine --list                # serial numbers of connected blink(1)s
  blink1-shine --version             # library version, and firmware if connected

Note --switch-off is off by default, so the light stays lit after the command exits. This is the opposite of the blink1() context manager, which switches off unless told otherwise.

--list and --version work with nothing plugged in. --version still reports the library version, and says no device is connected.

blink1-flash flashes between two colors at a given rate:

  blink1-flash --on white --off black --repeat 5
  blink1-flash --duration 1.5 --fade 0.1
  blink1-flash --serial 20002345

Both report a missing blink(1) or an unrecognized color as a one-line error rather than a traceback. Run either with --help for the full list of options.

For examples, see the blink1_demo directory for several examples on how to use this library.

OS-specific notes

The blink1-python library relies on cython-hidapi for USB HID access. This package may require a C compiler and attendant utilities to be installed before installing this library.

Linux:

The following extra packages must be installed:

  sudo apt-get install python3-dev libusb-1.0-0-dev libudev-dev

And udev rules for non-root user access to blink(1) devices:

  echo 'SUBSYSTEM=="usb", ATTRS{idVendor}=="27b8", ATTRS{idProduct}=="01ed", MODE:="666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-blink1.rules
  sudo udevadm control --reload
  sudo udevadm trigger

Mac OS X:

Install Xcode with command-line tools.

Windows:

You may need the Microsoft C++ Build Tools

Use

The standard API has open/use/close semantics:

  import time
  from blink1 import Blink1

  b1 = Blink1()
  b1.fade_to_rgb(1000, 64, 64, 64)
  time.sleep(3)
  b1.fade_to_rgb(1000, 255, 255, 255)
  b1.close()

Note you must .close() a blink(1) after opening it.

To avoid having to explicitly open/close, use via a context manager.

  import time
  from blink1.blink1 import blink1

  with blink1() as b1:
    b1.fade_to_color(100, 'navy')
    time.sleep(10)

When the blink1() block exits the light is automatically switched off. To leave it lit, use with blink1(switch_off=False).

To list all connected blink(1) devices:

  from blink1 import Blink1
  blink1_serials = Blink1.list()
  print("blink(1) devices found: " + ','.join(blink1_serials))

To open a particular blink(1) device by serial number, pass its serial number as a string:

  from blink1 import Blink1
  b1 = Blink1(serial_number='20002345')
  b1.fade_to_rgb(1000, 255,0,255)
  b1.close()

The context manager takes the same argument:

  with blink1(serial_number='20002345') as b1:
    b1.fade_to_color(1000, 'purple')

Import styles

The short form works from the package itself:

  from blink1 import Blink1

The pre-1.0 fully-qualified form keeps working, and is the only way to get the context manager under its original name:

  from blink1.blink1 import Blink1, blink1

The context manager is also re-exported from the package as blink1_ctx. It is not exported as blink1, because the package and its main module share that name and rebinding it would break import blink1.blink1.

The package also exports the exception classes, ColorCorrect, kelvin_to_rgb, COLOR_TEMPERATURES, VENDOR_ID, PRODUCT_ID and __version__:

  from blink1 import Blink1, Blink1ConnectionFailed, InvalidColor
  from blink1 import COLOR_TEMPERATURES, __version__

Blink1 is itself a context manager, so this works too:

  with Blink1() as b1:
    b1.fade_to_color(100, 'navy')

Note the difference from blink1(): leaving a with Blink1() block closes the device but leaves the light on. Only blink1() switches it off for you.

Colors

There are a number of ways to specify colors in this library:

  b1.fade_to_color(1000, '#ffffff') # Hexadecimal RGB as a string
  b1.fade_to_color(1000, 'green') # Named color - any color name understood by css3
  b1.fade_to_color(1000, (22,33,44)) # RGB as a tuple, each 0 <= lum <= 255
  b1.fade_to_color(1000, [22,33,44]) # a list works too

An unknown color name, a malformed hexcode, a sequence that is not three channels, or a channel outside 0-255 all raise InvalidColor.

Pattern playing

The blink(1) device has a non-volatile color pattern memory. This color pattern plays automatically if power is applied but not connected to a computer. You can also trigger this pattern (or sub-patterns) over USB, leaving your application free to do other things besides blink lights.

The memory holds 16 lines on a mk2 and 32 on an mk3. The library works out which from the firmware version when it opens the device, and exposes the result as b1.pattern_lines. Pass Blink1(pattern_lines=...) to set it yourself and skip the detection.

Each line in the color pattern consists of an R,G,B triplet and a fade time to reach that color.

To play the pattern in blink(1) or sub-patterns:

b1.play()  # play entire color pattern, infinitely looped
b1.stop()  # stop a color pattern playing (if playing)

b1.play(2,3, count=7)  # play color pattern lines 2,3 in a loop 7 times

To alter the lines of the pattern memory:

# write 100msec fades to green then yellow then black at lines 3,4,5
b1.write_pattern_line( 100, 'green',  3)
b1.write_pattern_line( 100, 'yellow', 4)
b1.write_pattern_line( 100, 'black',  5)

b1.play( 3,5, 4)  # play that sub-loop 4 times

A pos outside the device's pattern memory raises ValueError, as does an ledn outside 0-2. On a mk2 that means lines 0-15 only.

write_pattern_line applies gamma correction, while read_pattern_line returns the raw device values, so reading a line and writing it back would compound the correction. Pass read_pattern_line(pos, uncorrect=True) to undo it and get back roughly what you wrote.

To save the pattern to non-volatile memory (overwriting the factory pattern):

b1.save_pattern()

To quickly play a pattern in Blink1Control-style string format:

# play purple on LED1 in 300ms, green on LED2 in 100ms, then swap, for 10 times
pattern_str = '10, #ff00ff,0.3,1, #00ff00,0.1,2,  #ff00ff,0.3,2, #00ff00,0.1,1'
b1.play_pattern(pattern_str)
# wait 5 seconds while the pattern plays on the blink1
# (or go do something more useful)
time.sleep(5.0)
# flash purple-off 5 times fast on all LEDs
b1.play_pattern('5, #FF00FF,0.2,0,#000000,0.2,0')

Be aware that play_pattern overwrites the whole pattern memory, filling any lines the string does not cover with black. That is what makes the pattern it plays deterministic, but it discards anything written with write_pattern_line beforehand.

Pass on_device=False to play the pattern in the Python process instead of on the blink(1), which blocks until it finishes. The original onDevice spelling still works.

Reading device state

To read the current color of an LED:

r, g, b, fade_millis = b1.read_rgb()      # 0 = all/first LED
r, g, b, fade_millis = b1.read_rgb(2)     # LED B

The device stores the gamma-corrected value that was sent to it, so a plain read gives back a darker triplet than you wrote. Pass uncorrect=True to map it back:

b1.fade_to_rgb(0, 200, 100, 50)
b1.read_rgb()                  # (157, 39, 10, 0) on the default gamma
b1.read_rgb(uncorrect=True)    # (200, 100, 50, 0)

fade_millis is always set to zero in current blink(1) firmware. This may change in the future.

To find out whether a color pattern is playing, and where it is up to:

state = b1.read_play_state()
# PlayState(playing=True, start_pos=0, end_pos=31, repeats=3, pos=1)
if state.playing:
    print("on line", state.pos, "with", state.repeats, "plays left")

repeats is how many plays remain, with 0 meaning forever. The field is called repeats rather than count because a tuple already has a count method.

Startup parameters

A blink(1) plugged into a USB charger with no computer decides for itself what to do. On firmware 206+ and above devices, you can set that:

from blink1 import BOOT_NORMAL, BOOT_PLAY, BOOT_OFF

b1.get_startup_params()
# StartupParams(bootmode=0, start_pos=0, end_pos=31, repeats=0)

# play pattern lines 0-5 forever whenever it powers up unattached
b1.set_startup_params(BOOT_PLAY, 0, 5, 0)

b1.set_startup_params(BOOT_OFF)       # stay dark
b1.set_startup_params(BOOT_NORMAL)    # factory behavior

This setting is non-volatile: it survives unplugging. On firmware older than 206 the commands are not implemented and fail silently, so check b1.get_version() if you need to be sure.

Servertickle watchdog

blink(1) also has a "watchdog" of sorts called "servertickle". When enabled, you must periodically send it to the blink(1) or it will trigger, playing the stored color pattern. This is useful to announce a computer that has crashed. The blink(1) will flash on its own until told otherwise.

To use, enable servertickle with a timeout value (max timeout 62 seconds):

b1.server_tickle(enable=True, timeout_millis=2000)

Gamma correction

Both Blink1 and the context manager take a gamma argument, letting you supply a per-channel gamma correction value.

  import time
  from blink1.blink1 import blink1

  with blink1(gamma=(3, 3, 3)) as b1:
    b1.fade_to_color(100, 'pink')
    time.sleep(10)

This example provides a gamma correction of 3 to each of the three colour channels. The library default is (2, 2, 2).

Higher values of gamma make the blink(1) appear more colorful but decrease the brightness of colours.

White point correction

The human eye's perception of color can be influenced by ambient lighting. In some circumstances it may be desirable to apply a small color correction in order to make colors appear more accurate. For example, if we were operating the blink(1) in a room lit predominantly by candle-light:

  from blink1.blink1 import blink1

  with blink1(white_point='candle', switch_off=False) as b1:
    b1.fade_to_color(100, 'white')

Viewed in daylight this would make the Blink(1) appear yellowish, however in a candle-lit room this would be perceived as a more natural white. If we did not apply this kind of color correction the Blink(1) would appear blueish.

The following values are acceptable white-points:

  • Any triple of (r,g,b). Each 0 <= luminance <= 255
  • Any color_temperature expressed as an integer or float in Kelvin. The conversion is only meaningful between 1000 K and 40000 K, and values outside that are clamped to it with a logged warning.
  • A color temperature name. An unrecognized name raises UnknownWhitePoint, which is both an InvalidColor and a KeyError.

The library supports the following temperature names: candle, sunrise, incandescent, tungsten, halogen, sunlight, overcast, shade, blue-sky, warm-fluorescent, fluorescent, cool-fluorescent

API reference

Generated with python3 -m pydoc blink1.blink1, trimmed of inherited boilerplate. Exceptions: Blink1ConnectionFailed (a RuntimeError), InvalidColor (a ValueError) and UnknownWhitePoint (both an InvalidColor and a KeyError).

    class Blink1(builtins.object)
     |  Blink1(
     |      serial_number: 'str | None' = None,
     |      gamma: 'Sequence[float] | None' = None,
     |      white_point: 'WhitePoint | None' = None,
     |      pattern_lines: 'int | None' = None
     |  ) -> 'None'
     |
     |  Light controller class, sends messages to the blink(1) via USB HID.
     |
     |  Methods defined here:
     |
     |  __enter__(self) -> "'Blink1'"
     |
     |  __exit__(self, exc_type: 'object', exc_value: 'object', traceback: 'object') -> 'None'
     |
     |  __init__(
     |      self,
     |      serial_number: 'str | None' = None,
     |      gamma: 'Sequence[float] | None' = None,
     |      white_point: 'WhitePoint | None' = None,
     |      pattern_lines: 'int | None' = None
     |  ) -> 'None'
     |      :param serial_number: serial number of blink(1) to open, otherwise first found
     |      :param gamma: Triple of gammas for each channel e.g. (2, 2, 2)
     |      :param white_point: White point as (r,g,b), Kelvin, or a name
     |      :param pattern_lines: size of the device's color pattern memory.
     |          Detected from the firmware version when left as None.
     |      :raises: Blink1ConnectionFailed: if blink(1) is not present
     |
     |  clear_pattern(self) -> 'None'
     |      Clear entire color pattern in blink(1)
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  close(self) -> 'None'
     |      Close the connection to the blink(1). Safe to call twice.
     |
     |  detect_pattern_lines(self) -> 'int'
     |      Ask the firmware how big the color pattern memory is.
     |
     |      Falls back to the mk3 size on any failure, which is what the
     |      library assumed unconditionally before this existed.
     |
     |  fade_to_color(self, fade_milliseconds: 'float', color: 'Color', ledn: 'int' = 0) -> 'None'
     |      Fade the light to a known colour
     |      :param fade_milliseconds: Duration of the fade in milliseconds
     |      :param color: Named color to fade to (e.g. "#FF00FF", "red")
     |      :param ledn: which led to control
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  fade_to_rgb(
     |      self,
     |      fade_milliseconds: 'float',
     |      red: 'float',
     |      green: 'float',
     |      blue: 'float',
     |      ledn: 'int' = 0
     |  ) -> 'None'
     |      Command blink(1) to fade to RGB color
     |      :param fade_milliseconds: millisecs duration of fade
     |      :param red: 0-255
     |      :param green: 0-255
     |      :param blue: 0-255
     |      :param ledn: which LED to control (0=all, 1=LED A, 2=LED B)
     |      :raises: InvalidColor: if a channel is not a number in 0-255
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  fade_to_rgb_uncorrected(self, fade_milliseconds, red, green, blue, ledn=0)
     |      Command blink(1) to fade to RGB color, no color correction applied.
     |      :raises: Blink1ConnectionFailed if blink(1) is disconnected
     |
     |  get_serial_number(self) -> 'str'
     |      Get blink(1) serial number
     |      :return blink(1) serial number as string
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  get_startup_params(self) -> 'StartupParams'
     |      Read what the blink(1) does when powered with no computer
     |      :return StartupParams of (bootmode, start_pos, end_pos, repeats)
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |      Needs firmware 206+ or an mk3; older devices answer with
     |      whatever the unimplemented command leaves in the buffer.
     |
     |  get_version(self) -> 'str'
     |      Get blink(1) firmware version
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  off(self) -> 'None'
     |      Switch the blink(1) off instantly
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  play(self, start_pos: 'int' = 0, end_pos: 'int' = 0, count: 'int' = 0) -> 'None'
     |      Play internal color pattern
     |      :param start_pos: pattern line to start from
     |      :param end_pos: pattern line to end at
     |      :param count: number of times to play, 0=play forever
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  play_pattern(
     |      self,
     |      pattern_str: 'str',
     |      onDevice: 'bool' = True,
     |      *,
     |      on_device: 'bool | None' = None
     |  ) -> 'None'
     |      Play a Blink1Control-style pattern string
     |      :param pattern_str: The Blink1Control-style pattern string to play
     |      :param onDevice: True (default) to run pattern on blink(1),
     |                       otherwise plays in Python process
     |      :param on_device: snake_case spelling of onDevice; wins if given
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |      Note this overwrites the whole pattern memory, which is what
     |      makes the played pattern deterministic.
     |
     |  play_pattern_local(self, pattern_str: 'str') -> 'None'
     |      Play a Blink1Control pattern string in Python process
     |          (plays in blink1-python, so blocks)
     |      :param pattern_str: The Blink1Control-style pattern string to play
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  read(self) -> 'List[int]'
     |      Read command result from blink(1), low-level internal use
     |      Receive USB Feature Report 0x01 from blink(1) with 8-byte payload
     |      Note: buf must be 8 bytes or bad things happen
     |      :raises: Blink1ConnectionFailed if blink(1) is disconnected or closed
     |
     |  read_pattern(self, uncorrect: 'bool' = False) -> 'List[Tuple[Any, ...]]'
     |      Read the entire color pattern
     |      :param uncorrect: see read_pattern_line()
     |      :return List of pattern line tuples
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  read_pattern_line(self, pos: 'int', uncorrect: 'bool' = False) -> 'Tuple[Any, ...]'
     |      Read a color pattern line at position
     |      :param pos: pattern line to read
     |      :param uncorrect: undo the gamma correction write_pattern_line()
     |          applied, so a read-modify-write round trip does not compound it
     |      :return pattern line data as tuple (r,g,b, step_millis)
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  read_play_state(self) -> 'PlayState'
     |      Read whether a color pattern is playing, and where
     |      :return PlayState of (playing, start_pos, end_pos, repeats, pos)
     |          where repeats is how many plays are left, 0 meaning forever
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  read_rgb(self, ledn: 'int' = 0, uncorrect: 'bool' = False) -> 'Tuple[Any, ...]'
     |      Read the current color of an LED
     |      :param ledn: which LED to read (0=all/first, 1=LED A, 2=LED B)
     |      :param uncorrect: undo the gamma correction applied on the way out,
     |          so the value resembles what was passed to fade_to_rgb()
     |      :return tuple of (r, g, b, fade_millis)
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |      fade_millis is the protocol's remaining-fade field, but an mk3 on
     |      firmware 302 answers 0 for it even mid-fade. Do not rely on it.
     |
     |  save_pattern(self) -> 'None'
     |      Save internal RAM pattern to flash
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  server_tickle(
     |      self,
     |      enable,
     |      timeout_millis=0,
     |      stay_lit=False,
     |      start_pos=0,
     |      end_pos=16
     |  )
     |      Enable/disable servertickle / serverdown watchdog
     |      :param: enable: Set True to enable serverTickle
     |      :param: timeout_millis: millisecs until servertickle is triggered
     |      :param: stay_lit: Set True to keep current color of blink(1), False to turn off
     |      :param: start_pos: Sub-pattern start position in whole color pattern
     |      :param: end_pos: Sub-pattern end position in whole color pattern
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  set_ledn(self, ledn: 'int' = 0) -> 'None'
     |      Set the 'current LED' value for writePatternLine
     |      :param ledn: LED to adjust, 0=all, 1=LEDA, 2=LEDB
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  set_startup_params(
     |      self,
     |      bootmode: 'int' = 0,
     |      start_pos: 'int' = 0,
     |      end_pos: 'int' = 0,
     |      count: 'int' = 0
     |  ) -> 'None'
     |      Set what the blink(1) does when powered with no computer
     |      :param bootmode: BOOT_NORMAL, BOOT_PLAY or BOOT_OFF
     |      :param start_pos: sub-pattern start line, for BOOT_PLAY
     |      :param end_pos: sub-pattern end line, for BOOT_PLAY
     |      :param count: times to play, 0=forever
     |      :raises: ValueError: if bootmode or a position is out of range
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |      This is non-volatile: it outlives unplugging the device. Needs
     |      firmware 206+ or an mk3, and fails silently on older devices.
     |
     |  stop(self)
     |      Stop internal color pattern playing
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |  write(self, buf: 'Sequence[int]') -> 'None'
     |      Write command to blink(1), low-level internal use
     |      Send USB Feature Report 0x01 to blink(1) with 8-byte payload
     |      Note: arg 'buf' must be 8 bytes or bad things happen
     |      :raises: Blink1ConnectionFailed if blink(1) is disconnected or closed
     |
     |  write_pattern_line(
     |      self,
     |      step_milliseconds: 'float',
     |      color: 'Color',
     |      pos: 'int',
     |      ledn: 'int' = 0
     |  ) -> 'None'
     |      Write a color & step time color pattern line to RAM
     |      :param step_milliseconds: how long for this pattern line to take
     |      :param color: LED color
     |      :param pos: color pattern line number, 0 to pattern_lines-1
     |      :param ledn: LED number to adjust, 0=all, 1=LEDA, 2=LEDB
     |      :raises: ValueError: if pos is outside the device's pattern memory
     |      :raises: Blink1ConnectionFailed: if blink(1) is disconnected
     |
     |      Note this applies gamma correction, while read_pattern_line()
     |      returns raw device values.
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  color_to_rgb(color: 'Color') -> 'RGB'
     |      Convert color name, hexcode or (r,g,b) sequence to an (r,g,b) tuple
     |      :param color: a color string, e.g. "#FF00FF" or "red", or an
     |          (r,g,b) tuple or list with each channel 0-255
     |      :raises: InvalidColor: if the color cannot be interpreted
     |
     |  find(serial_number: 'str | None' = None)
     |      Find a particular blink(1) device, or the first one
     |      :param serial_number: serial number of blink(1) device (from Blink1.list())
     |      :raises: Blink1ConnectionFailed: if blink(1) is not present
     |
     |  list() -> 'List[str]'
     |      List blink(1) devices connected, by serial number
     |      :return: List of blink(1) device serial numbers
     |
     |  notfound() -> 'None'
     |      Deprecated, always returns None. Use Blink1ConnectionFailed instead.
     |
     |  parse_pattern(pattern_str: 'str') -> 'Tuple[int, List[dict]]'
     |      Parse a Blink1Control pattern string to a list of pattern lines
     |          e.g. of the form '10,#ff00ff,0.1,0,#00ff00,0.1,0'
     |      :param pattern_str: The Blink1Control-style pattern string to parse
     |      :returns: tuple of (num_repeats, list of pattern line dicts)
     |      :raises: ValueError: if the repeat count or a field is unparseable
     |
     |      Omitted and empty fields take their defaults, so
     |      '2,#ff99cc,,0.3' parses rather than raising.
     |

    class ColorCorrect(builtins.object)
     |  ColorCorrect(gamma: 'Sequence[float]', white_point: 'WhitePoint') -> 'None'
     |
     |  Apply a gamma correction to any selected RGB color, see:
     |  http://en.wikipedia.org/wiki/Gamma_correction
     |
     |  Methods defined here:
     |
     |  __call__(self, r: 'float', g: 'float', b: 'float') -> 'RGB'
     |      Call self as a function.
     |
     |  __init__(self, gamma: 'Sequence[float]', white_point: 'WhitePoint') -> 'None'
     |      :param gamma: Tuple of r,g,b gamma values
     |      :param white_point: White point expressed as (r,g,b), integer color
     |          temperature (in Kelvin) or a string value.
     |      :raises: UnknownWhitePoint: if white_point names no known temperature
     |
     |      Gamma values above 1 darken mid-tones; the library default is
     |      (2, 2, 2). Values below 1 brighten them.
     |
     |  uncorrect(self, r: 'float', g: 'float', b: 'float') -> 'RGB'
     |      Undo __call__, mapping device values back towards the input range.
     |
     |  ----------------------------------------------------------------------
     |  Static methods defined here:
     |
     |  gamma_correct(gamma: 'float', white: 'float', luminance: 'float') -> 'int'
     |
     |  gamma_uncorrect(gamma: 'float', white: 'float', value: 'float') -> 'int'
     |

FUNCTIONS
    blink1(
        switch_off: 'bool' = True,
        gamma: 'Sequence[float] | None' = None,
        white_point: 'WhitePoint | None' = None,
        serial_number: 'str | None' = None,
        pattern_lines: 'int | None' = None
    ) -> 'Iterator[Blink1]'
        Context manager which automatically shuts down the Blink(1)
        after use.
        :param switch_off: turn blink(1) off when exiting context
        :param gamma: set gamma curve (as tuple)
        :param white_point: set white point (as tuple)
        :param serial_number: serial number of blink(1) to open, otherwise first found
        :param pattern_lines: size of color pattern memory, detected if None

Developer installation

Having checked out the blink1-python library, cd to its directory and run the setup script:

  git clone https://github.com/todbot/blink1-python
  cd blink1-python
  pip3 install --editable ".[dev]"
  python3 ./blink1_demo/demo1.py

You can now use the blink1 package on your system and edit it.

To run the tests, which do not need a blink(1) attached:

  pytest

Tests that do need a real device are marked hardware and skipped unless you ask for them:

  pytest --run-hardware

To get internal blink1 library debug, messages set the environment variable DEBUGBLINK1:

DEBUGBLINK1=1 python3 ./blink1_demo/demo_logging.py

To uninstall the development version:

  pip3 uninstall blink1

Metadata

Release files for blink1 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for blink1 1.1.0
File Size Uploaded
blink1-1.1.0.tar.gz 30.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for blink1 1.1.0
File Interpreter ABI Platform
blink1-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 53.0 kB

Release files / blink1-1.1.0.tar.gz

Download URL blink1-1.1.0.tar.gz
Size 30.1 kB
Tags Source
SHA-256 checksum
How to use checksums
0eeac815a5d744511ce2fb2fe9dec8e18563cda8b4733c7b806bb91c88abb933
BLAKE2b-256 checksum
How to use checksums
32d799232ea2937e546af1e0d2e3e2aab39ae65591ba59abf8504cdd0c91b1f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / blink1-1.1.0-py3-none-any.whl

Download URL blink1-1.1.0-py3-none-any.whl
Size 23.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d60c8d5b0e9e15c10908d858623d2bf0c6fb91d41af4944e5b26d266207afd30
BLAKE2b-256 checksum
How to use checksums
95a4f77b99268c5329487816efa3585e946588653c95cb15b81f214412d2ef02
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files

1.0.1

2 release files

1.0.0

2 release files

0.4.0

2 release files

0.3.1

1 release file

0.3.0

1 release file

0.2.3

1 release file

0.2.1

1 release file

0.1.3

1 release file

0.1.2

1 release file

0.1.1

1 release file

0.1.0

1 release file

0.0.12

2 release files

0.0.11

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.5

2 release files

0.0.4

1 release file

0.0.3

2 release files

0.0.2

1 release file

0.0.1

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page