blink1

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Oct 27, 2023 License: MIT Imports: 13 Imported by: 5

README

blink1-go

Go Reference GitHub Actions

Yet another Go SDK for blink(1) USB RGB LED notification devices but tightened to perfection

Welcome to blink1-go, your Go SDK destination for blink(1) USB RGB LED notification devices delivering an enhanced user experience and extended functionalities.

Far from just another SDK, blink1-go was conceived and designed to overcome the limitations and challenges faced by the currently available SDK packages like GoBlink, go-blink1. Equipped with a fully implemented feature set, streamlined dependency management, and a user-friendly approach, blink1-go enables users with enhanced customization and simplicity, accommodating a wide range of use-cases.

  1. Simplified Dependencies: Avoiding the convoluted dependency packages and external USB HID libraries prevalent in the existing alternatives, b1ug/blink1-go adopts the b1ug/gid package. It uses native APIs to orchestrate USB HID operations on macOS and Windows, leverages libusb 1.0+ on Linux.

  2. Complete HID Command Suite: Breaking away from the partial HID command implementations, blink1-go ensures the implementation of all blink(1) mk2 HID commands. Users can easily apply these commands leveraging the Device API incorporated in the blink1-go package.

  3. Strategically Crafted APIs: Uniquely constituted, the well-thought Controller API provides an intuitive interface for pattern and state management, making the SDK adaptable to a wide range of use cases, broadening the horizon of usage possibilities.

  4. Color Helpers: blink1-go includes helpers offering predefined colors and color-conversion functionalities, enabling users to easily customize their device colors.

  5. Sophisticated Schemata: It boasts highly refined schemata for pattern and state representation. Coupled with effective serialization and deserialization methods, it ensures seamless compatibility with both JSON and natural language (English), thus offering a more human-readable and comfortable programming experience.

Installation

Installation remains a simple and very straightforward process with the go get command:

go get -u github.com/b1ug/blink1-go@latest

Please note that Go version 1.13 or higher and Cgo is required.

Usage

Here's how to use the Device API to instantly set all LEDs to blue:

import (
	b1 "github.com/b1ug/blink1-go"
)

func main() {
	d, err := b1.OpenNextDevice()
	if err != nil {
		panic(err)
	}
	defer d.Close()

	if err := d.SetRGBNow(0, 0, 0xff, b1.LEDAll); err != nil {
		panic(err)
	}
}

And here's how to use the Controller API to fade LED 1 to blue and LED 2 to red over 1 second:

func main() {
	c, err := b1.OpenNextController()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	s1 := b1.NewLightState(b1.ColorBlue, 1*time.Second, b1.LED1)
	s2 := b1.NewLightState(b1.ColorRed, 1*time.Second, b1.LED2)
	if err := c.PlayState(s1); err != nil {
		panic(err)
	}
	if err := c.PlayState(s2); err != nil {
		panic(err)
	}
}

If you want to get the state from a natural language query, you can try this:

func main() {
	st, err := b1.ParseStateQuery("Fade the first LED to blue in 1.5 seconds.")
	if err != nil {
		panic(err)
	}
	fmt.Println(st)
}

For more examples, please refer to go.dev.

Contributing

Your contributions are greatly appreciated! Whether you spot a bug, propose an improvement, or wish to add a new feature, your contributions help make this package and blink(1) device better.

License

As an open-source project, the blink1-go package is licensed under the MIT license, making it free and accessible for all.

Documentation

Overview

Package blink1 facilitates interaction with the blink(1) mk2 USB RGB LED notification light through both a low-level and high-level interface. The low-level interface, embodied in the Device type, provides direct access to the device by offering a range of HID command APIs. Conversely, the high-level interface, represented by the Controller type, simplifies device access by providing a user-friendly API suited for task execution.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ColorApricot is a predefined color, it's a light orange color similar to the color of an apricot fruit, having the RGB values #FBCEB1
	ColorApricot = color.RGBA{R: 0xFB, G: 0xCE, B: 0xB1, A: 0xFF}
	// ColorBeige is a predefined color, which is a very pale yellowish-brown color, having the RGB values #F5F5DC
	ColorBeige = color.RGBA{R: 0xF5, G: 0xF5, B: 0xDC, A: 0xFF}
	// ColorBlack is a predefined color, which absorbs all light in the visible wavelengths, having the RGB values #000000
	ColorBlack = color.RGBA{R: 0x00, G: 0x00, B: 0x00, A: 0xFF}
	// ColorBlue is a predefined color, which is one of the primary additive colors, having the RGB values #0000FF
	ColorBlue = color.RGBA{R: 0x00, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorBronze is a predefined color, it resembles the color of the metal bronze, having the RGB values #CD7F32
	ColorBronze = color.RGBA{R: 0xCD, G: 0x7F, B: 0x32, A: 0xFF}
	// ColorBrown is a predefined color, which is a composite color produced by mixing red, yellow, and black, having the RGB values #A52A2A
	ColorBrown = color.RGBA{R: 0xA5, G: 0x2A, B: 0x2A, A: 0xFF}
	// ColorCyan is a predefined color (a.k.a. Aqua), which is a greenish-blue color, having the RGB values #00FFFF
	ColorCyan = color.RGBA{R: 0x00, G: 0xFF, B: 0xFF, A: 0xFF}
	// ColorGold is a predefined color, which resembles the metal gold, having the RGB values #FFD700
	ColorGold = color.RGBA{R: 0xFF, G: 0xD7, B: 0x00, A: 0xFF}
	// ColorGray is a predefined color (a.k.a. Grey), which is an intermediate color between black and white, having the RGB values #808080
	ColorGray = color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xFF}
	// ColorGreen is a predefined color, which is one of the primary additive colors, having the RGB values #00FF00
	ColorGreen = color.RGBA{R: 0x00, G: 0xFF, B: 0x00, A: 0xFF}
	// ColorIndigo is a predefined color, which is a mix of blue and violet, having the RGB values #4B0082
	ColorIndigo = color.RGBA{R: 0x4B, G: 0x00, B: 0x82, A: 0xFF}
	// ColorLavender is a predefined color, it's a light purple color similar to lavender flowers, having the RGB values #E6E6FA
	ColorLavender = color.RGBA{R: 0xE6, G: 0xE6, B: 0xFA, A: 0xFF}
	// ColorLime is a predefined color, which is a fluorescent green, having the RGB values #00FF00
	ColorLime = color.RGBA{R: 0x00, G: 0x80, B: 0x00, A: 0xFF}
	// ColorMagenta is a predefined color (a.k.a. Fuchsia), which is a mix of red and blue, having the RGB values #FF00FF
	ColorMagenta = color.RGBA{R: 0xFF, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorMaroon is a predefined color, which is a dark brownish red color, having the RGB values #800000
	ColorMaroon = color.RGBA{R: 0x80, G: 0x00, B: 0x00, A: 0xFF}
	// ColorMint is a predefined color, which is a pale greenish-blue color, having the RGB values #16982B
	ColorMint = color.RGBA{R: 0x16, G: 0x98, B: 0x2B, A: 0xFF}
	// ColorNavy is a predefined color, which is a very dark shade of blue, having the RGB values #000080
	ColorNavy = color.RGBA{R: 0x00, G: 0x00, B: 0x80, A: 0xFF}
	// ColorOlive is a predefined color, which resembles unripe green olives, having the RGB values #808000
	ColorOlive = color.RGBA{R: 0x80, G: 0x80, B: 0x00, A: 0xFF}
	// ColorOrange is a predefined color, which is between red and yellow, having the RGB values #FFA500
	ColorOrange = color.RGBA{R: 0xFF, G: 0xA5, B: 0x00, A: 0xFF}
	// ColorPeach is a predefined color, it's similar to the color of a peach fruit, having the RGB values #FFE5B4
	ColorPeach = color.RGBA{R: 0xFF, G: 0xE5, B: 0xB4, A: 0xFF}
	// ColorPink is a predefined color, which is a pale red color, having the RGB values #FFC0CB
	ColorPink = color.RGBA{R: 0xFF, G: 0xC0, B: 0xCB, A: 0xFF}
	// ColorPlum is a predefined color, it's a dark purple color similar to the color of a plum fruit, having the RGB values #8E4585
	ColorPlum = color.RGBA{R: 0x8E, G: 0x45, B: 0x85, A: 0xFF}
	// ColorPurple is a predefined color, which is a mix of red and blue, having the RGB values #800080
	ColorPurple = color.RGBA{R: 0x80, G: 0x00, B: 0x80, A: 0xFF}
	// ColorRed is a predefined color, which is one of the primary additive colors, having the RGB values #FF0000
	ColorRed = color.RGBA{R: 0xFF, G: 0x00, B: 0x00, A: 0xFF}
	// ColorScarlet is a predefined color, which is a bright red color with a slightly orange tinge, having the RGB values #FF2400
	ColorScarlet = color.RGBA{R: 0xFF, G: 0x24, B: 0x00, A: 0xFF}
	// ColorSilver is a predefined color, which resembles gray metallic silver, having the RGB values #C0C0C0
	ColorSilver = color.RGBA{R: 0xC0, G: 0xC0, B: 0xC0, A: 0xFF}
	// ColorTeal is a predefined color, which is a dark cyan color, having the RGB values #008080
	ColorTeal = color.RGBA{R: 0x00, G: 0x80, B: 0x80, A: 0xFF}
	// ColorViolet is a predefined color, which is a mix of blue and red, having the RGB values #8000FF
	ColorViolet = color.RGBA{R: 0x80, G: 0x00, B: 0xFF, A: 0xFF}
	// ColorWhite is a predefined color, which reflects all visible wavelengths of light, having the RGB values #FFFFFF
	ColorWhite = color.RGBA{R: 0xFF, G: 0xFF, B: 0xFF, A: 0xFF}
	// ColorYellow is a predefined color, which is one of the primary subtractive colors, having the RGB values #FFFF00
	ColorYellow = color.RGBA{R: 0xFF, G: 0xFF, B: 0x00, A: 0xFF}

	// RainbowColors is a predefined color palette, which contains the 7 colors of the rainbow.
	RainbowColors = []color.Color{ColorRed, ColorOrange, ColorYellow, ColorGreen, ColorCyan, ColorBlue, ColorViolet}
)

Functions

func ColorToHex

func ColorToHex(cl color.Color) string

ColorToHex converts color.Color to hex string with leading #. e.g. color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff} -> "#FF0000" However, if you need color names instead of hex strings, use GetNameByColor()/GetNameOrHexByColor() methods instead.

func ColorToRGB

func ColorToRGB(cl color.Color) (r, g, b uint8)

ColorToRGB converts color.Color to 8-bit RGB values. e.g. color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff} -> 0xff, 0x00, 0x00

func DecodeGammaColor

func DecodeGammaColor(cl color.Color) color.Color

DecodeGammaColor operates gamma correction on the given color and returns the decoded color. The gamma correction is automatically applied for state and pattern while playing or writing. This is the inverse function of EncodeGammaColor.

func EncodeGammaColor

func EncodeGammaColor(cl color.Color) color.Color

EncodeGammaColor operates gamma correction on the given color and returns the encoded color. Encoding a decoded color may not return the original color, but it will be the same color when decoded again.

func FindDeviceInfoBySerialNumber

func FindDeviceInfoBySerialNumber(sn string) (*hid.DeviceInfo, error)

FindDeviceInfoBySerialNumber finds a connected blink(1) device with serial number and returns its HID device info.

func FindNextDeviceInfo

func FindNextDeviceInfo() (di *hid.DeviceInfo, err error)

FindNextDeviceInfo returns the next HID device info of a blink(1) device which is connected to the system.

func GetColorByName

func GetColorByName(name string) (cl color.Color, found bool)

GetColorByName returns the color corresponding to the given name from the preset color map. If the color is found, it returns the color and true, otherwise it returns nil and false.

func GetColorNames

func GetColorNames() []string

GetColorNames returns the color names from the preset color map.

func GetNameByColor

func GetNameByColor(cl color.Color) (name string, found bool)

GetNameByColor returns the name corresponding to the given color from the preset color map. If the color is found, it returns the name and true. If the color is not found, it returns the hex string and false.

func GetNameOrHexByColor

func GetNameOrHexByColor(cl color.Color) string

GetNameOrHexByColor returns the name corresponding to the given color from the preset color map, or the hex string if the color is not found.

func HSBToRGB

func HSBToRGB(hue, sat, bright float64) (red, green, blue uint8)

HSBToRGB converts HSB to 8-bit RGB values. e.g. 0, 100, 100 -> 0xff, 0x00, 0x00 The hue is in degrees [0, 360], saturation and brightness/value are percent in the range [0, 100]. Values outside of these ranges will be clamped.

func HexToColor

func HexToColor(hex string) (color.Color, error)

HexToColor converts hex string to color.Color. The hex string can be in the format of #RRGGBB or #RGB or RRGGBB or RGB (case insensitive). e.g. "#FF0000" -> color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff} However, if you want to convert color names to color.Color, use GetColorByName() instead. And if your input string is more complex and diverse than hex or names, use ParseColor() instead.

func HexToRGB

func HexToRGB(hex string) (r, g, b uint8, err error)

HexToRGB converts hex string to 8-bit RGB values. The underlying implementation is HexToColor() + ColorToRGB(). e.g. "#FF0000" -> 0xff, 0x00, 0x00

func IsBlink1Device

func IsBlink1Device(di *hid.DeviceInfo) bool

IsBlink1Device returns true if the device info is about a blink(1) device.

func IsRunningOnSupportedOS

func IsRunningOnSupportedOS() bool

IsRunningOnSupportedOS returns true if the current OS is supported by underlying HID library.

Example

This example checks if the current OS is supported by the underlying HID library.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	fmt.Println(b1.IsRunningOnSupportedOS())
}
Output:

func ListDeviceInfo

func ListDeviceInfo() []*hid.DeviceInfo

ListDeviceInfo returns all HID device info of all blink(1) devices which are connected to the system. The returned slice is sorted by serial number.

func ParseColor

func ParseColor(query string) (color.Color, error)

ParseColor parses the case-insensitive unstructured description of color and returns the corresponding color.Color.

func ParseRepeatTimes

func ParseRepeatTimes(query string) (uint, error)

ParseRepeatTimes parses the case-insensitive unstructured description of repeat times and returns the number of times to repeat.

Example

This example shows how to parse a repeat times query.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	rt, err := b1.ParseRepeatTimes("Repeat 3 times")
	if err != nil {
		panic(err)
	}
	fmt.Println(rt)

}
Output:

3

func ParseTitle

func ParseTitle(query string) (string, error)

ParseTitle parses the labeled title or topic or idea string from the query string. It returns the title or an error if no title is found.

Example

This example shows how to parse a title query.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	t, err := b1.ParseTitle("title: Hawaiian Rainbow")
	if err != nil {
		panic(err)
	}
	fmt.Println(t)

}
Output:

Hawaiian Rainbow

func Preload

func Preload()

Preload triggers the initialization of the parsers and color names. It's optional to call this function, and it's safe to call it multiple times. Currently there is no noticeable performance gain from calling this function before using other APIs.

func RGBToColor

func RGBToColor(r, g, b uint8) color.Color

RGBToColor converts 8-bit RGB values to color.Color. e.g. 0xff, 0x00, 0x00 -> color.RGBA{R: 0xff, G: 0x00, B: 0x00, A: 0xff}

func RGBToHex

func RGBToHex(r, g, b uint8) string

RGBToHex converts 8-bit RGB values to hex string with leading #. e.g. 0xff, 0x00, 0x00 -> "#FF0000"

func RandomColor

func RandomColor() color.Color

RandomColor returns a bright random color.

Example

This example shows how to get a random color.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	cl := b1.RandomColor()
	fmt.Println(b1.GetNameOrHexByColor(cl))
}
Output:

Types

type Controller

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

Controller provides a high-level API for operating blink(1) devices, abstracting away the low-level details.

func NewController

func NewController(dev *Device) *Controller

NewController creates a blink(1) controller for existing device instance.

func OpenController

func OpenController(info *hid.DeviceInfo) (*Controller, error)

OpenController opens a blink(1) controller for device which is connected to the system.

func OpenControllerBySerialNumber

func OpenControllerBySerialNumber(sn string) (*Controller, error)

OpenControllerBySerialNumber finds a connected blink(1) device with serial number and opens it as controller.

func OpenNextController

func OpenNextController() (*Controller, error)

OpenNextController opens the next blink(1) device which is connected to the system and returns as controller.

func (*Controller) Close

func (c *Controller) Close()

Close closes the device and release the kept resources.

func (*Controller) GetDevice

func (c *Controller) GetDevice() *Device

GetDevice returns the underlying blink(1) device.

func (*Controller) GetFirmwareVersion

func (c *Controller) GetFirmwareVersion() (int, error)

GetFirmwareVersion returns the firmware version of the device.

func (*Controller) GetPatternState

func (c *Controller) GetPatternState() (PatternState, error)

GetPatternState returns the current state of the pattern that is playing.

func (*Controller) IsPatternPlaying

func (c *Controller) IsPatternPlaying() (bool, error)

IsPatternPlaying returns true if the pattern is playing.

func (*Controller) LoadPattern

func (c *Controller) LoadPattern(posStart, posEnd uint, seq StateSequence) error

LoadPattern writes the given pattern to the device's RAM and it will be lost after the device is powered off. To save the pattern to the device's flash, call WritePattern() after calling this function.

func (*Controller) PlayColor

func (c *Controller) PlayColor(cl color.Color) error

PlayColor fades the all LED to the specified RGB color immediately.

Example

This example shows how to play a color on the blink(1) device.

package main

import (
	b1 "github.com/b1ug/blink1-go"
)

func main() {
	c, err := b1.OpenNextController()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	c.PlayColor(b1.ColorBlue)
}
Output:

func (*Controller) PlayHSB

func (c *Controller) PlayHSB(hue, saturation, brightness float64) error

PlayHSB fades the all LED to the specified HSB/HSV color immediately. Valid hue range is [0, 360], saturation range and brightness/value range is [0, 100]. Values outside of the valid range will be clamped to the range.

func (*Controller) PlayPattern

func (c *Controller) PlayPattern(pt Pattern) error

PlayPattern plays the given pattern. If the pattern has no states, it will only play the pattern without writing states to the device's RAM

func (*Controller) PlayPatternBlocking

func (c *Controller) PlayPatternBlocking(pt Pattern) error

PlayPatternBlocking plays the given pattern, and blocks until the pattern is finished. It may block forever if the pattern is set to loop forever. If the pattern has no states, it will only play the pattern without writing states to the device's RAM, and blocks until the pattern is finished.

Example

This example illustrates how to generate a state sequence for Hawaiian rainbow on the blink(1) device, looping it thrice, and pausing until the execution completes.

package main

import (
	"time"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	// build a rainbow sequence with 2 states for each color, one for fade in and one for maintain
	seq := make(b1.StateSequence, len(b1.RainbowColors)*2)
	for i, cl := range b1.RainbowColors {
		st := b1.NewLightState(cl, 300*time.Millisecond, b1.LEDAll)
		seq[i*2] = st
		seq[i*2+1] = st
	}
	pat := b1.Pattern{
		StartPosition: 0,
		EndPosition:   uint(seq.Length() - 1),
		RepeatTimes:   3,
		Sequence:      seq,
	}

	// open the device and play the pattern
	c, err := b1.OpenNextController()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	c.PlayPatternBlocking(pat)

	// turn off all LEDs
	c.StopPlaying()
}
Output:

func (*Controller) PlayRGB

func (c *Controller) PlayRGB(r, g, b byte) error

PlayRGB fades the all LED to the specified RGB color immediately.

func (*Controller) PlayState

func (c *Controller) PlayState(st LightState) error

PlayState fades the given LED to the specified RGB color over the specified time.

Example

This example shows how to fade to a RGB color on the blink(1) device.

package main

import (
	"time"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	c, err := b1.OpenNextController()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	st := b1.NewLightStateRGB(0, 0, 0xff, time.Second, b1.LED1)
	c.PlayState(st)
}
Output:

func (*Controller) PlayStateBlocking

func (c *Controller) PlayStateBlocking(st LightState) error

PlayStateBlocking fades the given LED to the specified RGB color over the specified time, and blocks until the fade is finished.

func (*Controller) ReadColor

func (c *Controller) ReadColor(ledN LEDIndex) (color.Color, error)

ReadColor reads the current color of the specified LED.

Example

This example shows how to read the current color of the first LED of the blink(1) device.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	c, err := b1.OpenNextController()
	if err != nil {
		panic(err)
	}
	defer c.Close()

	if cl, err := c.ReadColor(b1.LED1); err != nil {
		panic(err)
	} else {
		fmt.Println(b1.GetNameOrHexByColor(cl))
	}
}
Output:

func (*Controller) ReadPattern

func (c *Controller) ReadPattern() (StateSequence, error)

ReadPattern reads the current pattern in the device's RAM.

func (*Controller) SetGammaCorrection

func (c *Controller) SetGammaCorrection(on bool)

SetGammaCorrection sets the gamma correction on/off for the controller. Default is on. If it is true, the gamma correction will be applied for state and pattern while playing or writing.

func (*Controller) SimpleTickle

func (c *Controller) SimpleTickle(posStart, posEnd uint, timeout time.Duration, keepOld bool) error

SimpleTickle sets the device to tickle once. The timeout should be at least 10ms, or it will be ignored by the firmware. An error will be returned for this case. If keepOld is true, the current pattern will be kept playing, otherwise it will be stopped.

func (*Controller) StartAutoTickle

func (c *Controller) StartAutoTickle(posStart, posEnd uint, keepOld bool) error

StartAutoTickle sets the device to automatically tickle every 2 seconds. If the auto tickle is already started, it will be stopped and restarted. If keepOld is true, the current pattern will be kept playing, otherwise it will be stopped.

To stop the auto tickle, call StopAutoTickle().

func (*Controller) StartManualTickle

func (c *Controller) StartManualTickle(posStart, posEnd uint, timeout time.Duration, keepOld bool) (chan<- struct{}, error)

StartManualTickle sets the device to tickle manually. The timeout should be at least 10ms, or it will be ignored by the firmware. An error will be returned for this case. Signals should be sent to the returned channel to tickle before the timeout, otherwise the given pattern will be played. If keepOld is true, the current pattern will be kept playing, otherwise it will be stopped.

To stop the manual tickle, close the returned channel.

func (*Controller) StopAutoTickle

func (c *Controller) StopAutoTickle()

StopAutoTickle stops the device from automatically tickling.

func (*Controller) StopPlaying

func (c *Controller) StopPlaying() error

StopPlaying stops playing the pattern and turns off all the LEDs. It will stop the current playing patterns, whether it is started by StartPlaying() or StartAuto/ManualTickle(), and turn off all the LEDs. If the pattern is not playing, it only turns off all the LEDs. It will NOT stop the auto/manual tickle.

func (*Controller) String

func (c *Controller) String() string

func (*Controller) WritePattern

func (c *Controller) WritePattern() error

WritePattern writes the pattern stored in the device's RAM to its flash. For mk2 device, only the first 16 patterns can be saved.

type Device

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

Device represents a blink(1) device and provides low-level APIs using HID commands for direct control.

func OpenDevice

func OpenDevice(info *hid.DeviceInfo) (*Device, error)

OpenDevice opens a blink(1) device which is connected to the system.

func OpenDeviceBySerialNumber

func OpenDeviceBySerialNumber(sn string) (*Device, error)

OpenDeviceBySerialNumber finds a connected blink(1) device with serial number and opens it as device.

func OpenNextDevice

func OpenNextDevice() (*Device, error)

OpenNextDevice opens the next blink(1) device which is connected to the system and returns as device.

func (*Device) Close

func (b1 *Device) Close()

Close closes the device and release the kept resources.

func (*Device) FadeToRGB

func (b1 *Device) FadeToRGB(r, g, b byte, fadeMsec uint, ledN LEDIndex) error

FadeToRGB fades the given LED to the specified RGB color over the specified time.

The fadeMsec parameter specifies the fade time in milliseconds, fade time less than 10ms will be processed as no fade time by the firmware. The ledN parameter specifies which LED to control: 0=all, 1=top LED, 2=bottom LED.

Returns an error if there was a problem communicating with the device.

func (*Device) GetDeviceInfo

func (b1 *Device) GetDeviceInfo() *hid.DeviceInfo

GetDeviceInfo returns the HID device info.

func (*Device) GetGeneration

func (b1 *Device) GetGeneration() uint16

GetGeneration returns the generation number.

func (*Device) GetProductName

func (b1 *Device) GetProductName() string

GetProductName returns the product name.

func (*Device) GetSerialNumber

func (b1 *Device) GetSerialNumber() string

GetSerialNumber returns the serial number.

func (*Device) GetVersion

func (b1 *Device) GetVersion() (ver int, err error)

GetVersion returns the firmware version of the device.

Returns an error if there was a problem communicating with the device.

func (*Device) PlayLoop

func (b1 *Device) PlayLoop(play bool, posStart, posEnd, times uint) error

PlayLoop starts or stops a sub-loop of the color pattern.

The play parameter specifies whether to start or stop the loop. The posStart and posEnd parameters specify the start and end positions of the loop, where positions should be [0, patt_max-1]. If posEnd is 0, it will be set to patt_max by the firmware. There is no check for posStart < posEnd, and the device will play the loop in even if posStart > posEnd, i.e. the loop will play from posStart to maxPos-1 and then 0 to posEnd. The times parameter specifies how many times to play the loop, 0 means infinite.

Returns an error if the arguments are invalid or there was a problem communicating with the device.

func (*Device) ReadPatternLine

func (b1 *Device) ReadPatternLine(pos uint) (st DeviceLightState, err error)

ReadPatternLine reads the specified pattern line.

The pos parameter specifies the position of the pattern line, where pos should be [0, patt_max).

Returns the DeviceLightState struct containing the RGB values and the LEDType, or an error if there was invalid pattern position or a problem communicating with the device.

func (*Device) ReadPlaystate

func (b1 *Device) ReadPlaystate() (st DevicePatternState, err error)

ReadPlaystate reads the current playing state of the pattern loop.

Returns the DevicePatternState struct containing the loop state and the current position, or an error if there was a problem communicating with the device.

func (*Device) ReadRGB

func (b1 *Device) ReadRGB(ledN LEDIndex) (r, g, b byte, err error)

ReadRGB reads the current RGB color of the specified LED.

The ledN parameter specifies which LED to control: 0=all, 1=top LED, 2=bottom LED. For mk2+ devices, ledN == 0 will return the RGB values of the first LED.

Returns the RGB values or an error if there was a problem communicating with the device.

func (*Device) SavePattern

func (b1 *Device) SavePattern() error

SavePattern saves the current pattern to the device.

Returns an error if there was a problem communicating with the device.

func (*Device) SetPatternLine

func (b1 *Device) SetPatternLine(pos uint, st DeviceLightState) error

SetPatternLine sets the specified pattern line to the specified DeviceLightState.

The pos parameter specifies the position of the pattern line, where pos should be [0, patt_max). The st parameter specifies the DeviceLightState to set.

Returns an error if the arguments are invalid or there was a problem communicating with the device.

func (*Device) SetRGBNow

func (b1 *Device) SetRGBNow(r, g, b byte, ledN LEDIndex) error

SetRGBNow sets the given LED to the specified RGB color immediately.

The ledN parameter specifies which LED to control: 0=all, 1=top LED, 2=bottom LED. For mk2+ devices, ledN > 0 will set all LEDs to the white color (255, 255, 255) and ignore the RGB values due to a firmware bug.

Returns an error if there was a problem communicating with the device.

func (*Device) SetTickleMode

func (b1 *Device) SetTickleMode(play, keep bool, posStart, posEnd, timeoutMsec uint) error

SetTickleMode sets the device to server tickle mode, which will play the pattern from the specified start position to the specified end position after the specified timeout.

The play parameter specifies whether to start or stop the tickle mode. The keep parameter specifies whether to keep the current pattern playing state or not. The posStart and posEnd parameters specify the start and end positions of the loop, where positions should be [0, patt_max-1]. If posEnd is 0, it will be set to patt_max by the firmware. The timeoutMsec parameter specifies the timeout in milliseconds, timeout should be at least 10ms, or it will be ignored by the firmware.

Returns an error if there was a problem communicating with the device.

func (*Device) String

func (b1 *Device) String() string

func (*Device) Test

func (b1 *Device) Test() ([]byte, error)

Test sends a test command to the device, and returns the response.

Returns the response from the device, or an error if there was a problem communicating with the device.

Example

This example shows how to run test command on the blink(1) device.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	d, err := b1.OpenNextDevice()
	if err != nil {
		panic(err)
	}
	defer d.Close()

	if data, err := d.Test(); err != nil {
		panic(err)
	} else {
		fmt.Println(data)
	}
}
Output:

type DeviceLightState

type DeviceLightState struct {
	R, G, B      byte     // RGB values
	LED          LEDIndex // Which LED to address (0=all, 1=1st LED, 2=2nd LED)
	FadeTimeMsec uint     // Fade time in milliseconds
}

DeviceLightState is a blink(1) light state for low-level APIs.

func (DeviceLightState) String

func (st DeviceLightState) String() string

type DevicePatternState

type DevicePatternState struct {
	IsPlaying    bool // Is playing
	CurrentPos   uint // Current position
	LoopStartPos uint // Loop start position, inclusive
	LoopEndPos   uint // Loop end position, exclusive
	RepeatTimes  uint // Remaining times to repeat
}

DevicePatternState is a blink(1) pattern playing state for low-level APIs.

func (DevicePatternState) String

func (st DevicePatternState) String() string

type LEDIndex

type LEDIndex byte

LEDIndex represents LED on the blink(1) device

const (
	// LEDAll represents all LEDs on the blink(1) device
	LEDAll LEDIndex = iota
	// LED1 represents the first LED on the blink(1) device, usually the top one, with 'blink(1)' label
	LED1
	// LED2 represents the second LED on the blink(1) device, usually the bottom one, with 'ThingM' logo
	LED2
)

func (LEDIndex) String

func (l LEDIndex) String() string

String returns a string representation of LEDIndex.

func (LEDIndex) ToByte

func (l LEDIndex) ToByte() byte

ToByte converts LEDType to byte, and returns 0 if the LEDType is invalid.

type LightState

type LightState struct {
	Color    color.Color   // Color to set
	LED      LEDIndex      // Which LED to address (0=all, 1=1st LED, 2=2nd LED)
	FadeTime time.Duration // Fade time to state
}

LightState is a composite data type that represents the state of a light in a blink(1) high-level APIs context. It includes three fields: Color, LED, and FadeTime.

The Color field, a value of type color.Color, represents the color to be set for the LightState. The LED field, a value of type LEDIndex, represents which LED to address. Here, 0 represents all LEDs, 1 represents the 1st LED, and 2 represents the 2nd LED. The FadeTime field, a value of type time.Duration, represents the fade time to the LightState, specified in duration.

This struct is serialized in string format with three components, separated by specific letters for ease of understanding and clean formatting:

#RRGGBBL{0,1,2}T{fade time in milliseconds}

1. Color is converted to hexadecimal (HEX) representation using convColorToHex function;
2. LED is represented by its corresponding LEDIndex value prefixed by 'L';
3. FadeTime is represented by its millisecond value prefixed by 'T';

For example, a reddish color (Hex #FF0000), targeting LED 1, with a fade time of 200ms would be serialized as "#FF0000L1T200".

func NewLightState

func NewLightState(cl color.Color, fadeTime time.Duration, ledN LEDIndex) LightState

NewLightState returns a new LightState with the given color and fade time.

func NewLightStateHSB

func NewLightStateHSB(h, s, b float64, fadeTime time.Duration, ledN LEDIndex) LightState

NewLightStateHSB returns a new LightState with the given HSB/HSV color and fade time. Valid hue range is [0, 360], saturation range and brightness/value range is [0, 100].

func NewLightStateRGB

func NewLightStateRGB(r, g, b uint8, fadeTime time.Duration, ledN LEDIndex) LightState

NewLightStateRGB returns a new LightState with the given RGB color and fade time.

func ParseStateQuery

func ParseStateQuery(query string) (LightState, error)

ParseStateQuery parses the case-insensitive unstructured description of light state and returns the structured LightState. The query can contain information about the color, fade time, and LED index. For example, "turn off all lights right now", "set led 1 to color #ff00ff over 2 sec", "#FF0000L1T500". If the query is empty, it returns an error.

Color can be specified by name, hex code, or RGB/HSB values, e.g. "red", "#FF0000", "rgb(255,0,0)", "hsb(0,100,100)"

Fade time can be specified by milliseconds, seconds, or minutes, e.g. "100ms", "1s", "1.5m", "now", "0s"

LED index can be specified by number, name, or position, e.g. "led 1", "led 2", "top led", "second led", "led:all", "led:0"

Example

This example shows how to parse a state query.

package main

import (
	"fmt"

	b1 "github.com/b1ug/blink1-go"
)

func main() {
	st, err := b1.ParseStateQuery("Fade the first LED to blue in 1.5 seconds.")
	if err != nil {
		panic(err)
	}
	fmt.Println(st)

}
Output:

🎨(color=#0000FF led=1 fade=1.5s)

func (LightState) MarshalText

func (st LightState) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface.

func (LightState) String

func (st LightState) String() string

String method is used to represent a LightState in string format for human comprehension, annotating each element by its field name, and using emojis and symbols for clarity and aesthetics. For example: 🎨(color=#FF0000 led=1 fade=200ms)

func (*LightState) UnmarshalText

func (st *LightState) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

type Pattern

type Pattern struct {
	StartPosition uint          // Loop start position, inclusive
	EndPosition   uint          // Loop end position, inclusive
	RepeatTimes   uint          // How many times to repeat, 0 means infinite
	Sequence      StateSequence // Sequence of states to execute in pattern, non-empty patterns will be set to the device automatically
}

Pattern is a sequence of LightState to play on blink(1).

func (Pattern) String

func (p Pattern) String() string

type PatternState

type PatternState struct {
	IsPlaying       bool // Is playing
	CurrentPosition uint // Current position
	StartPosition   uint // Loop start position, inclusive
	EndPosition     uint // Loop end position, exclusive
	RepeatTimes     uint // Remaining times to repeat
}

PatternState represents a blink(1) pattern playing state for high-level APIs.

func (PatternState) String

func (st PatternState) String() string

type StateSequence

type StateSequence []LightState

StateSequence is a data type that represents a sequence of LightState, used to define the sequence of states to be played on the blink(1) device. The type is essentially a slice of LightState.

func (StateSequence) Length

func (seq StateSequence) Length() int

Length returns the length of the sequence.

func (StateSequence) MarshalText

func (seq StateSequence) MarshalText() (text []byte, err error)

MarshalText implements the encoding.TextMarshaler interface. This method will convert a StateSequence into a string of semicolon-separated state sequences. However, the individual states are expected to be marshalled using the LightState MarshalText method before joining together into a single string. For example, a sequence of two states might be serialized as "#FF0000L1T200;#00FF00L2T300".

func (StateSequence) String

func (seq StateSequence) String() string

String method is used to output the StateSequence in a human-readable string format.

If the sequence is empty, it returns "🔄(empty)". This means that there are no light states in this sequence.

If the length of the sequence is exactly 1, it simply outputs the lone LightState in the sequence, as there are no additional states in the sequence to specify. For example, "🔄(#FF0000L1T200)" would indicate a single state of reddish color LED1 with a fade time of 200ms as the sole state in the sequence.

If there is more than one LightState in the sequence, it prints out the first LightState in the sequence and the count of LightStates, separated by dots. For example, "🔄(#FF0000L1T200...5)" indicates a sequence of 5 states, starting with a reddish color LED1 with a fade time of 200ms. This is the default case when there are more than one states in the sequence.

func (StateSequence) TotalTime

func (seq StateSequence) TotalTime() time.Duration

TotalTime returns the total time of the sequence.

func (*StateSequence) UnmarshalText

func (seq *StateSequence) UnmarshalText(text []byte) error

UnmarshalText implements the encoding.TextUnmarshaler interface.

Jump to

Keyboard shortcuts

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