blink

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 3, 2016 License: MIT Imports: 10 Imported by: 0

README

Build Status GoDoc License

blink is a go implementation for controlling ThingM blink(1) USB dual RGB LEDs.

Features

  • Fade to RGB color
  • Set RGB color now
  • Read current RGB color (mk2 devices only)
  • Serverdown tickle/off
  • Play/Pause
  • PlayLoop (mk2 devices only)
  • Playstate readback (mk2 devices only)
  • Set color pattern line
  • read color pattern line
  • Save color patterns (mk2 devices only)
  • Read EEPROM location (mk1 devices only)
  • Write EEPROM location (mk1 devices only)
  • Get version
  • Test command

Installation

Currently blink does only compile on linux and requires libusb-1.0.12 or higher. blink is build on travis using libusb 1.0.20. Refer to the .travis.yml to it can be built on ubuntu. On Fedora 22 you can simply use dnf install libusb-devel.

Use go get to install blink:

go get gopkg.in/fgrosse/blink.v1

You need to have go version 1.4 or higher.

Usage

Simple usage

// connect to a local blink(1) USB device
led, err := blink.New()
if err != nil {
    panic(err)
}

// disable all lights and close the device when you are done
defer led.FadeOutClose()

// fade to a full green in 500ms
d := 500 * time.Millisecond
led.FadeRGB(0, 255, 0, d)
time.Sleep(d)

// store colors for later use
corpBlue := blink.MustParseColor("#3333ff")
led.Fade(corpBlue, d)

// read the current color
color, err := led.Read()
if err != nil {
    panic(err)
}
fmt.Printf("%#v\n", color)

Create sequences to store and playback multiple instructions

d := 500 * time.Millisecond
s := blink.NewSequence().
    Fade(blink.Red, d).
    Fade(blink.Green, d).
    Fade(blink.Blue, d).
    Wait(1 * time.Second).
    Off()

// blocks until s is done
err = s.Play(led)
if err != nil {
    panic(err)
}

Sequences can be run in a loop. You can also loop multiple sections.

firstLoop := blink.NewSequence().
    Fade(blink.Red, 250*time.Millisecond).
    Fade(blink.Blue, 250*time.Millisecond).
    LoopN(2) // loops 2 times

secondLoop := firstLoop.
    Fade(blink.Green, 250*time.Millisecond).
    LoopN(4) // loops 4 times starting at the first fade to red

myBlue := blink.MustParseColor("#6666ff")
entireLoop, c := secondLoop.
    Start(). // instruct the next loop to start at this position
    Set(myBlue, 200 * time.Millisecond).
    Set(myBlue.Multiply(0.8), 200 * time.Millisecond).
    Set(myBlue.Multiply(0.6), 200 * time.Millisecond).
    Set(myBlue.Multiply(0.4), 200 * time.Millisecond).
    Loop() // restarts the sequence until c is closed

go func() {
    // stop the whole loop after ten seconds
    time.Sleep(10 * time.Second)
    close(c)
}()

err = entireLoop.Play(led)
Linux Permissions

You need to have root access when running this program or you will get the following error:

libusb: bad access [code -3]

On linux this problem can easily be fixed by adding the following udev rule:

[root@localhost]# cat /etc/udev/rules.d/10.local.rules
SUBSYSTEMS=="usb", ATTRS{idVendor}=="27b8", ATTRS{idProduct}=="01ed", SYMLINK+="blink1", GROUP="blink1"

Everybody in the blink1 group should now be able to access the device directly. Additionally this rule creates a symlink at /dev/blink1 each time you connect the device. You probably need to reconnect your device so the change will be visible.

Other resources

Contributing

Any contributions are always welcome (use pull requests). Please keep in mind that I might not always be able to respond immediately but I usually try to react within the week ☺.

Documentation

Overview

Package blink provides an interface to ThingM blink(1) USB RGB LEDs

+build linux

Example
package main

import (
	"fmt"
	"time"

	"github.com/fgrosse/blink"
)

func main() {
	// connect to a local blink(1) USB device
	led, err := blink.New()
	if err != nil {
		panic(err)
	}

	// disable all lights and close the device when you are done
	defer led.FadeOutClose()

	// fade to a full green in 500ms
	d := 500 * time.Millisecond
	led.FadeRGB(0, 255, 0, d)
	time.Sleep(d)

	// store colors for later use
	corpBlue := blink.MustParseColor("#3333ff")
	led.Fade(corpBlue, d)

	// read the current color
	color, err := led.Read()
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v\n", color)
}
Output:

Index

Examples

Constants

View Source
const (
	// VendorNumber is the USB vendor identifier as defined in github.com/todbot/blink1
	// https://github.com/todbot/blink1/blob/3c51231d302d7676c50f28debaf82adc5bfa9460/commandline/blink1-lib.h#L30
	VendorNumber = 0x27B8

	// ProductNumber is the USB device identifier as defined in github.com/todbot/blink1
	// https://github.com/todbot/blink1/blob/3c51231d302d7676c50f28debaf82adc5bfa9460/commandline/blink1-lib.h#L31
	ProductNumber = 0x01ED
)

Variables

View Source
var (
	Red    = Color{R: 255, G: 000, B: 000}
	Green  = Color{R: 000, G: 255, B: 000}
	Blue   = Color{R: 000, G: 000, B: 255}
	Yellow = Color{R: 255, G: 255, B: 000}
	White  = Color{R: 255, G: 255, B: 255}
)
View Source
var ErrNoDevice = errors.New("could not find blink1 device")

ErrNoDevice is the error that New() returns if no connected blink(1) device was found.

View Source
var USBTimeOut = 1 * time.Second

USBTimeOut is the maximum duration a call to the USB device can take before it will result in an error.

Functions

This section is empty.

Types

type Color

type Color struct{ R, G, B byte }

Color contains the 24-bit RGB color information.

func MustParseColor added in v1.1.0

func MustParseColor(s string) Color

MustParseColor behaves exactly as ParseColor but panics if an error occurs.

func ParseColor added in v1.1.0

func ParseColor(s string) (c Color, err error)

ParseColor parses a Color from string. It accepts the RGB value either as comma separated vector or in hexadecimal form with a leading hash tag. Examples:

255,255,0
255, 255, 0
#ffff00
#FFFF00

func (Color) Add added in v1.1.0

func (c Color) Add(other Color) Color

Add returns a new color where every individual color channel is the result of adding up the corresponding value of this color an the given color. The maximum value of each color channel is always 0xFF (no overflows).

func (Color) Multiply added in v1.1.0

func (c Color) Multiply(f float64) Color

Multiply returns a copy of c where every individual color channel is multiplied with the given factor. The maximum value of each color channel is always 0xFF (no overflows). If f is lower than 0 it is ignored entirely and c is returned unchanged.

type LED

type LED struct {
	ID byte // ID signals which LED to address: 0=all, 1=led#1, 2=led#2, etc. (mk2 only)
	// contains filtered or unexported fields
}

LED represents a locally connected blink(1) USB device.

func New

func New() (*LED, error)

New connects to a locally connected blink(1) USB device. The caller must call Close when it is done with this LED. The function returns a NoDeviceErr if no blink(1) device can be found or another error if the device could not be opened.

Multiple connected devices are not yet supported and the library will just pick one of them to talk to.

func (*LED) Close

func (l *LED) Close() error

Close implements io.Closer by closing to the connection to the USB device. The function is idempotent and can be called on already closed or never opened devices.

func (*LED) Fade added in v1.1.0

func (l *LED) Fade(c Color, d time.Duration) error

Fade lights up the blink(1) with the specified RGB color, fading to that color over a specified duration.

func (*LED) FadeOutClose added in v1.1.0

func (l *LED) FadeOutClose(fadeDuration ...time.Duration) error

FadeOutClose can be used to disable all lights on the blink(1) device and then close this LED. The optional fadeDuration argument can be used to let the LED fade out smoothly. If it is omitted a default value if 1s is assumed. Examples:

defer l.FadeOutClose()
defer l.FadeOutClose(500 * time.Millisecond)

func (*LED) FadeRGB

func (l *LED) FadeRGB(r, g, b byte, d time.Duration) error

FadeRGB is a handy shortcut to LED.Fade(Color{r, g, b}, d)

func (*LED) Read added in v1.1.0

func (l *LED) Read() (Color, error)

Read reads the currently active color of the blink(1) device. Will return meaningful results for mk2 devices only.

func (*LED) ReadRGB

func (l *LED) ReadRGB() (Color, error)

ReadRGB is deprecated and will be removed in v2. Use LED.Read() instead. ReadRGB reads the currently active color of the blink(1) device. Will return meaningful results for mk2 devices only.

func (*LED) Set added in v1.1.0

func (l *LED) Set(c Color) error

Set lights up the blink(1) with the specified color immediately.

func (*LED) SetRGB

func (l *LED) SetRGB(r, g, b byte) error

SetRGB is a handy shortcut to LED.SetRGB(Color{r, g, b})

type Sequence added in v1.1.0

type Sequence struct {
	// contains filtered or unexported fields
}

A Sequence is used to store and send a set of commands to the blink(1) device in particular order. It enables you to define a sequence of actions like fading to another color, waiting a certain amount of time and looping.

A Sequence is not save for concurrent use.

Example
package main

import (
	"time"

	"github.com/fgrosse/blink"
)

func main() {
	led, err := blink.New()
	if err != nil {
		panic(err)
	}

	defer led.Close()

	d := 500 * time.Millisecond
	s := blink.NewSequence().
		Fade(blink.Red, d).
		Fade(blink.Green, d).
		Fade(blink.Blue, d).
		Wait(1 * time.Second).
		Off()

	// blocks until s is done
	err = s.Play(led)
	if err != nil {
		panic(err)
	}
}
Output:

func NewSequence added in v1.1.0

func NewSequence() *Sequence

NewSequence creates a new sequence and can be used to chain multiple sequence instructions Example:

s := blink.NewSequence().
    Fade(blink.Red, d).
    Fade(blink.Green, d).
    Fade(blink.Blue, d).
    Wait(1 * time.Second).
    Off()

func (*Sequence) Fade added in v1.1.0

func (s *Sequence) Fade(c Color, d time.Duration) *Sequence

Fade adds a new frame to the sequence which lets the led fade to another color.

func (*Sequence) Loop added in v1.1.0

func (s *Sequence) Loop() (*Sequence, chan<- struct{})

Loop is used to instruct the sequence to loop all previously added frames infinitely. The second return value is a channel that can be closed to stop the looping sequence after it has been started. Sending values to the channel does nothing. The loop frame works by resetting the sequence each time it is reached. Once the channel has been closed the loop will stop to reset the sequence.

Example
package main

import (
	"time"

	"github.com/fgrosse/blink"
)

func main() {
	led, err := blink.New()
	if err != nil {
		panic(err)
	}

	defer led.FadeOutClose()

	firstLoop := blink.NewSequence().
		Fade(blink.Red, 250*time.Millisecond).
		Fade(blink.Blue, 250*time.Millisecond).
		LoopN(2) // loops 2 times

	secondLoop := firstLoop.
		Fade(blink.Green, 250*time.Millisecond).
		LoopN(4) // loops 4 times

	myBlue := blink.MustParseColor("#6666ff")
	entireLoop, c := secondLoop.
		Start(). // instruct the next loop to start at this position
		Set(myBlue, 200*time.Millisecond).
		Set(myBlue.Multiply(0.8), 200*time.Millisecond).
		Set(myBlue.Multiply(0.6), 200*time.Millisecond).
		Set(myBlue.Multiply(0.4), 200*time.Millisecond).
		Loop() // restarts the sequence until c is closed

	go func() {
		// stop the whole loop after ten seconds
		time.Sleep(10 * time.Second)
		close(c)
	}()

	err = entireLoop.Play(led)
	if err != nil {
		panic(err)
	}
}
Output:

func (*Sequence) LoopN added in v1.1.0

func (s *Sequence) LoopN(n int) *Sequence

func (*Sequence) Off added in v1.1.0

func (s *Sequence) Off() *Sequence

Off adds a new frame to the sequence which deactivates the led immediately.

func (*Sequence) Play added in v1.1.0

func (s *Sequence) Play(led *LED) error

Play starts to playback this sequence on the given LED. It blocks until all frames have been processed. If this sequence loops Play will never return by itself.

func (*Sequence) Set added in v1.1.0

func (s *Sequence) Set(c Color, d time.Duration) *Sequence

Set adds a new frame to the sequence which immediately sets the led to another color and waits a given duration.

func (*Sequence) Start added in v1.1.0

func (s *Sequence) Start() *Sequence

func (*Sequence) Wait added in v1.1.0

func (s *Sequence) Wait(d time.Duration) *Sequence

Wait adds a new frame to the sequence which doesn't do anything for a given duration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL