| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292 |
- /*
- Copyright 2016 Denis V. Dedkov (denis.v.dedkov@gmail.com)
- This file is part of Noolite Go bindings.
- Noolite Go bindings is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Noolite Go bindings is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Noolite Go bindings. If not, see <http://www.gnu.org/licenses/>.
- */
- // Package noolite provide class for control Noolite Adapters PC11xx.
- // Protocol described on url:
- // http://www.noo.com.by/assets/files/software/PC11xx_HID_API.pdf
- package noolite
- import (
- "errors"
- "github.com/tonymagro/usb"
- )
- const (
- VID = 5824 // Vendor ID
- PID = 1503 // Product ID
- )
- // Available commands
- type command byte
- const (
- off command = iota
- decBrightnes
- on
- incBrightnes
- cSwitch
- invertBrightnes
- set
- callScenario
- saveScenario
- unbind
- stopColorSelection
- bind = iota + 0x04
- // Commands for SD111-180 only
- colorSelection
- colorSwitch
- modeSwitch
- effectSpeed
- )
- // Noolite Adapter class as USB HID
- type NooliteAdapter struct {
- *usb.Device
- mode byte
- }
- // Return NooliteAdapter object.
- //
- // work mode: range 0..7
- // bitrate: range 0..3
- // command repeats: range 0..7
- func NewNooliteAdapter(mode, bitrate, repeats uint) (*NooliteAdapter, error) {
- usb.Init()
- d := usb.Open(VID, PID)
- if d == nil {
- return nil, errors.New("Device not found")
- }
- if mode > 7 {
- return nil, errors.New("Mode must be in 0..7 range")
- }
- if bitrate > 3 {
- return nil, errors.New("Bitrate must be in 0..3 range")
- }
- if repeats > 7 {
- return nil, errors.New("Repeats must be in 0..7 range")
- }
- m := (byte(repeats) << 5) | (byte(bitrate) << 3) | byte(mode)
- d.Interface(0)
- if d.LastError() != "No error" {
- defer d.Close()
- return nil, errors.New(d.LastError())
- }
- return &NooliteAdapter{d, m}, nil
- }
- // Return NooliteAdapter object with default work mode values:
- //
- // work mode: 0
- // bitrate: 2 (for 1000 bit/sec)
- // command repeats: 2
- func DefaultNooliteAdapter() (*NooliteAdapter, error) { // Default constructor
- return NewNooliteAdapter(0, 2, 2)
- }
- // Return NooliteAdapter method for string command
- //
- // Set command must be separately processed because have different signature
- func (n *NooliteAdapter) FindCommand(command string) (func(int) error, bool) {
- m := map[string]func(int) error {
- "on": n.On,
- "off": n.Off,
- "switch": n.Switch,
- "decraseBrightnes": n.DecraseBrightnes,
- "incraseBrightnes": n.IncraseBrightnes,
- "invertBrightnes": n.InvertBrightnes,
- "callScenario": n.CallScenario,
- "saveScenario": n.SaveScenario,
- "unbind": n.UnbindChannel,
- "stopColorSelection": n.StopColorSelection,
- "bind": n.BindChannel,
- "colorSelection": n.ColorSelection,
- "colorSwitch": n.ColorSwitch,
- "modeSwitch": n.ModeSwitch,
- "effectSpeed": n.EffectSpeed,
- }
- cmd, ok := m[command]
- return cmd, ok
- }
- func (n *NooliteAdapter) composeCommand(cmd command, channel int, args ...int) []byte {
- c := make([]byte, 8)
- c[0] = n.mode
- c[1] = byte(cmd)
- c[4] = byte(channel)
- if cmd == set {
- l := len(args)
- switch l {
- case 1:
- {
- c[2] = 0x01
- c[5] = byte(args[0])
- }
- case 3:
- {
- c[2] = 0x03
- for i, v := range args {
- c[5+i] = byte(v)
- }
- }
- default:
- panic("Bad arguments for SET command")
- }
- }
- return c
- }
- func (n *NooliteAdapter) sendCommand(command []byte) error {
- n.ControlMsg(0x21, 0x09, 0x300, 0, command)
- if n.LastError() != "No error" {
- return errors.New(n.LastError())
- }
- return nil
- }
- // Turn power OFF for specified channel
- func (n *NooliteAdapter) Off(channel int) error {
- cmd := n.composeCommand(off, channel)
- return n.sendCommand(cmd)
- }
- // Smooth brightnes decrase for specified channel
- func (n *NooliteAdapter) DecraseBrightnes(channel int) error {
- cmd := n.composeCommand(decBrightnes, channel)
- return n.sendCommand(cmd)
- }
- // Turn power ON for specified channel
- func (n *NooliteAdapter) On(channel int) error {
- cmd := n.composeCommand(on, channel)
- return n.sendCommand(cmd)
- }
- // Smooth brightnes incrase for specified channel
- func (n *NooliteAdapter) IncraseBrightnes(channel int) error {
- cmd := n.composeCommand(incBrightnes, channel)
- return n.sendCommand(cmd)
- }
- // Switch power state between off and on for specified channel
- func (n *NooliteAdapter) Switch(channel int) error {
- cmd := n.composeCommand(cSwitch, channel)
- return n.sendCommand(cmd)
- }
- // Smooth brightnes incrase or decrase for specified channel
- func (n *NooliteAdapter) InvertBrightnes(channel int) error {
- cmd := n.composeCommand(invertBrightnes, channel)
- return n.sendCommand(cmd)
- }
- // Set brightnes value for specified channel
- //
- // Value must be in range 35..155.
- // When value == 0 lights off.
- // When value > 155 lights on for full brightness.
- func (n *NooliteAdapter) SetBrightnesValue(channel, value int) error {
- cmd := n.composeCommand(set, channel, value)
- return n.sendCommand(cmd)
- }
- // Set brightnes values for independens channels
- //
- // Available for SD111-180 only
- func (n *NooliteAdapter) SetBrightnesValues(channel, val1, val2, val3 int) error {
- cmd := n.composeCommand(set, channel, val1, val2, val3)
- return n.sendCommand(cmd)
- }
- // Call scenario for specified channel
- func (n *NooliteAdapter) CallScenario(channel int) error {
- cmd := n.composeCommand(callScenario, channel)
- return n.sendCommand(cmd)
- }
- // Save scenario for specified channel
- func (n *NooliteAdapter) SaveScenario(channel int) error {
- cmd := n.composeCommand(saveScenario, channel)
- return n.sendCommand(cmd)
- }
- // Unbind signal for specified channel
- func (n *NooliteAdapter) UnbindChannel(channel int) error {
- cmd := n.composeCommand(unbind, channel)
- return n.sendCommand(cmd)
- }
- // Stop color selection for specified channel
- //
- // Available for SD111-180 only
- func (n *NooliteAdapter) StopColorSelection(channel int) error {
- cmd := n.composeCommand(stopColorSelection, channel)
- return n.sendCommand(cmd)
- }
- // Set binding for specified channel
- func (n *NooliteAdapter) BindChannel(channel int) error {
- cmd := n.composeCommand(bind, channel)
- return n.sendCommand(cmd)
- }
- // Smooth color changing for specified channel
- //
- // Stop with StopColorSelection method
- //
- // Avialable for SD111-180 only
- func (n *NooliteAdapter) ColorSelection(channel int) error {
- cmd := n.composeCommand(colorSelection, channel)
- return n.sendCommand(cmd)
- }
- // Switch color for specified channel
- //
- // Avialable for SD111-180 only
- func (n *NooliteAdapter) ColorSwitch(channel int) error {
- cmd := n.composeCommand(colorSwitch, channel)
- return n.sendCommand(cmd)
- }
- // Switch work mode for specified channel
- //
- // Avialable for SD111-180 only
- func (n *NooliteAdapter) ModeSwitch(channel int) error {
- cmd := n.composeCommand(modeSwitch, channel)
- return n.sendCommand(cmd)
- }
- // Set change color speed for specified channel
- //
- // Avialable for SD111-180 only
- func (n *NooliteAdapter) EffectSpeed(channel int) error {
- cmd := n.composeCommand(effectSpeed, channel)
- return n.sendCommand(cmd)
- }
|