Move client library to separate repo
git.kill0.net/chill9/lifx-go
This commit is contained in:
		
							
								
								
									
										335
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										335
									
								
								client.go
									
									
									
									
									
								
							@@ -1,335 +0,0 @@
 | 
				
			|||||||
package lifx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	//"crypto/tls"
 | 
					 | 
				
			||||||
	"bytes"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"io"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"net/url"
 | 
					 | 
				
			||||||
	"strconv"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const defaultUserAgent = "lifx-go"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	Client struct {
 | 
					 | 
				
			||||||
		accessToken string
 | 
					 | 
				
			||||||
		userAgent   string
 | 
					 | 
				
			||||||
		Client      *http.Client
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Result struct {
 | 
					 | 
				
			||||||
		Id     string `json:"id"`
 | 
					 | 
				
			||||||
		Label  string `json:"label"`
 | 
					 | 
				
			||||||
		Status Status `json:"status"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Error struct {
 | 
					 | 
				
			||||||
		Field   string   `json:"field"`
 | 
					 | 
				
			||||||
		Message []string `json:"message"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Warning struct {
 | 
					 | 
				
			||||||
		Warning string `json:"warning"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	RateLimit struct {
 | 
					 | 
				
			||||||
		Limit     int
 | 
					 | 
				
			||||||
		Remaining int
 | 
					 | 
				
			||||||
		Reset     time.Time
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Response struct {
 | 
					 | 
				
			||||||
		StatusCode int
 | 
					 | 
				
			||||||
		Header     http.Header
 | 
					 | 
				
			||||||
		Body       io.ReadCloser
 | 
					 | 
				
			||||||
		RateLimit  RateLimit
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	LifxResponse struct {
 | 
					 | 
				
			||||||
		Error    string    `json:"error"`
 | 
					 | 
				
			||||||
		Errors   []Error   `json:"errors"`
 | 
					 | 
				
			||||||
		Warnings []Warning `json:"warnings"`
 | 
					 | 
				
			||||||
		Results  []Result  `json:"results"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var errorMap = map[int]error{
 | 
					 | 
				
			||||||
	http.StatusNotFound:            errors.New("Selector did not match any lights"),
 | 
					 | 
				
			||||||
	http.StatusUnauthorized:        errors.New("Bad access token"),
 | 
					 | 
				
			||||||
	http.StatusForbidden:           errors.New("Bad OAuth scope"),
 | 
					 | 
				
			||||||
	http.StatusUnprocessableEntity: errors.New("Missing or malformed parameters"),
 | 
					 | 
				
			||||||
	http.StatusUpgradeRequired:     errors.New("HTTP was used to make the request instead of HTTPS. Repeat the request using HTTPS instead"),
 | 
					 | 
				
			||||||
	http.StatusTooManyRequests:     errors.New("The request exceeded a rate limit"),
 | 
					 | 
				
			||||||
	http.StatusInternalServerError: errors.New("Something went wrong on LIFX's end"),
 | 
					 | 
				
			||||||
	http.StatusBadGateway:          errors.New("Something went wrong on LIFX's end"),
 | 
					 | 
				
			||||||
	http.StatusServiceUnavailable:  errors.New("Something went wrong on LIFX's end"),
 | 
					 | 
				
			||||||
	523:                            errors.New("Something went wrong on LIFX's end"),
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewClient(accessToken string, options ...func(*Client)) *Client {
 | 
					 | 
				
			||||||
	var c *Client
 | 
					 | 
				
			||||||
	tr := &http.Transport{
 | 
					 | 
				
			||||||
		//TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = &Client{
 | 
					 | 
				
			||||||
		accessToken: accessToken,
 | 
					 | 
				
			||||||
		Client:      &http.Client{Transport: tr},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, option := range options {
 | 
					 | 
				
			||||||
		option(c)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func WithUserAgent(userAgent string) func(*Client) {
 | 
					 | 
				
			||||||
	return func(c *Client) {
 | 
					 | 
				
			||||||
		c.userAgent = userAgent
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewClientWithUserAgent(accessToken string, userAgent string) *Client {
 | 
					 | 
				
			||||||
	tr := &http.Transport{
 | 
					 | 
				
			||||||
		//TLSNextProto: make(map[string]func(authority string, c *tls.Conn) http.RoundTripper),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &Client{
 | 
					 | 
				
			||||||
		accessToken: accessToken,
 | 
					 | 
				
			||||||
		userAgent:   userAgent,
 | 
					 | 
				
			||||||
		Client:      &http.Client{Transport: tr},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewResponse(r *http.Response) (*Response, error) {
 | 
					 | 
				
			||||||
	resp := Response{
 | 
					 | 
				
			||||||
		StatusCode: r.StatusCode,
 | 
					 | 
				
			||||||
		Header:     r.Header,
 | 
					 | 
				
			||||||
		Body:       r.Body,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if t := r.Header.Get("X-RateLimit-Limit"); t != "" {
 | 
					 | 
				
			||||||
		if n, err := strconv.ParseInt(t, 10, 32); err == nil {
 | 
					 | 
				
			||||||
			resp.RateLimit.Limit = int(n)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if t := r.Header.Get("X-RateLimit-Remaining"); t != "" {
 | 
					 | 
				
			||||||
		if n, err := strconv.ParseInt(t, 10, 32); err == nil {
 | 
					 | 
				
			||||||
			resp.RateLimit.Remaining = int(n)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if t := r.Header.Get("X-RateLimit-Reset"); t != "" {
 | 
					 | 
				
			||||||
		if n, err := strconv.ParseInt(t, 10, 32); err == nil {
 | 
					 | 
				
			||||||
			resp.RateLimit.Reset = time.Unix(n, 0)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return &resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *Response) IsError() bool {
 | 
					 | 
				
			||||||
	return r.StatusCode > 299
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (r *Response) GetLifxError() (err error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		s *LifxResponse
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(r.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return errors.New(s.Error)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) NewRequest(method, url string, body io.Reader) (req *http.Request, err error) {
 | 
					 | 
				
			||||||
	req, err = http.NewRequest(method, url, body)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", c.accessToken))
 | 
					 | 
				
			||||||
	req.Header.Add("Content-Type", "application/json")
 | 
					 | 
				
			||||||
	req.Header.Add("User-Agent", c.userAgent)
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) setState(selector string, state State) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		j    []byte
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if j, err = json.Marshal(state); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("PUT", EndpointState(selector), bytes.NewBuffer(j)); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) setStates(selector string, states States) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		j    []byte
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if j, err = json.Marshal(states); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("PUT", EndpointStates(), bytes.NewBuffer(j)); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) toggle(selector string, duration float64) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		j    []byte
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if j, err = json.Marshal(&Toggle{Duration: duration}); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("POST", EndpointToggle(selector), bytes.NewBuffer(j)); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) validateColor(color Color) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
		q    url.Values
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("GET", EndpointColor(), nil); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	q = req.URL.Query()
 | 
					 | 
				
			||||||
	q.Set("string", color.ColorString())
 | 
					 | 
				
			||||||
	req.URL.RawQuery = q.Encode()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) listLights(selector string) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("GET", EndpointListLights(selector), nil); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) stateDelta(selector string, delta StateDelta) (*Response, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		j    []byte
 | 
					 | 
				
			||||||
		req  *http.Request
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if j, err = json.Marshal(delta); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if req, err = c.NewRequest("POST", EndpointStateDelta(selector), bytes.NewBuffer(j)); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if r, err = c.Client.Do(req); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return resp, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -6,7 +6,7 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
	"github.com/BurntSushi/toml"
 | 
						"github.com/BurntSushi/toml"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package lumecmd
 | 
					package lumecmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func PoweroffCmd(args CmdArgs) (int, error) {
 | 
					func PoweroffCmd(args CmdArgs) (int, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package lumecmd
 | 
					package lumecmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func PoweronCmd(args CmdArgs) (int, error) {
 | 
					func PoweronCmd(args CmdArgs) (int, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,7 @@ package lumecmd
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SetColorCmd(args CmdArgs) (int, error) {
 | 
					func SetColorCmd(args CmdArgs) (int, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package lumecmd
 | 
					package lumecmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SetStateCmd(args CmdArgs) (int, error) {
 | 
					func SetStateCmd(args CmdArgs) (int, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
package lumecmd
 | 
					package lumecmd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SetWhiteCmd(args CmdArgs) (int, error) {
 | 
					func SetWhiteCmd(args CmdArgs) (int, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,7 +8,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lifx "git.kill0.net/chill9/lume"
 | 
						"git.kill0.net/chill9/lifx-go"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func powerColor(s string) string {
 | 
					func powerColor(s string) string {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										224
									
								
								color.go
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								color.go
									
									
									
									
									
								
							@@ -1,224 +0,0 @@
 | 
				
			|||||||
package lifx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	Color interface {
 | 
					 | 
				
			||||||
		ColorString() string
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	RGBColor struct {
 | 
					 | 
				
			||||||
		R, G, B uint8
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	HSBKColor struct {
 | 
					 | 
				
			||||||
		H *float32 `json:"hue"`
 | 
					 | 
				
			||||||
		S *float32 `json:"saturation"`
 | 
					 | 
				
			||||||
		B *float32 `json:"brightness"`
 | 
					 | 
				
			||||||
		K *int16   `json:"kelvin"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	NamedColor string
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	KelvinCandlelight    = 1500
 | 
					 | 
				
			||||||
	KelvinSunset         = 2000
 | 
					 | 
				
			||||||
	KelvinUltraWarm      = 2500
 | 
					 | 
				
			||||||
	KelvinIncandescent   = 2700
 | 
					 | 
				
			||||||
	KelvinWarm           = 3000
 | 
					 | 
				
			||||||
	KelvinCool           = 4000
 | 
					 | 
				
			||||||
	KelvinCoolDaylight   = 4500
 | 
					 | 
				
			||||||
	KelvinSoftDaylight   = 5000
 | 
					 | 
				
			||||||
	KelvinDaylight       = 5600
 | 
					 | 
				
			||||||
	KelvinNoonDaylight   = 6000
 | 
					 | 
				
			||||||
	KelvinBrightDaylight = 6500
 | 
					 | 
				
			||||||
	KelvinCloudDaylight  = 7000
 | 
					 | 
				
			||||||
	KelvinBlueDaylight   = 7500
 | 
					 | 
				
			||||||
	KelvinBlueOvercast   = 8000
 | 
					 | 
				
			||||||
	KelvinBlueIce        = 9000
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	HueWhite  = 0
 | 
					 | 
				
			||||||
	HueRed    = 0
 | 
					 | 
				
			||||||
	HueOrange = 36
 | 
					 | 
				
			||||||
	HueYellow = 60
 | 
					 | 
				
			||||||
	HueGreen  = 120
 | 
					 | 
				
			||||||
	HueCyan   = 180
 | 
					 | 
				
			||||||
	HueBlue   = 250
 | 
					 | 
				
			||||||
	HuePurple = 280
 | 
					 | 
				
			||||||
	HuePink   = 325
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	DefaultWhites = map[string]int{
 | 
					 | 
				
			||||||
		"candlelight":    KelvinCandlelight,
 | 
					 | 
				
			||||||
		"sunset":         KelvinSunset,
 | 
					 | 
				
			||||||
		"ultrawarm":      KelvinUltraWarm,
 | 
					 | 
				
			||||||
		"incandescent":   KelvinIncandescent,
 | 
					 | 
				
			||||||
		"warm":           KelvinWarm,
 | 
					 | 
				
			||||||
		"cool":           KelvinCool,
 | 
					 | 
				
			||||||
		"cooldaylight":   KelvinCoolDaylight,
 | 
					 | 
				
			||||||
		"softdaylight":   KelvinSoftDaylight,
 | 
					 | 
				
			||||||
		"daylight":       KelvinDaylight,
 | 
					 | 
				
			||||||
		"noondaylight":   KelvinNoonDaylight,
 | 
					 | 
				
			||||||
		"brightdaylight": KelvinBrightDaylight,
 | 
					 | 
				
			||||||
		"clouddaylight":  KelvinCloudDaylight,
 | 
					 | 
				
			||||||
		"bluedaylight":   KelvinBlueDaylight,
 | 
					 | 
				
			||||||
		"blueovercast":   KelvinBlueOvercast,
 | 
					 | 
				
			||||||
		"blueice":        KelvinBlueIce,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewRGBColor(r, g, b uint8) (RGBColor, error) {
 | 
					 | 
				
			||||||
	var c RGBColor
 | 
					 | 
				
			||||||
	if (r < 0 || r > 255) && (g < 0 || r > 255) && (b < 0 || b > 255) {
 | 
					 | 
				
			||||||
		return c, errors.New("values must be between 0-255")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return RGBColor{R: r, G: g, B: b}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewHSColor(h, s float32) (HSBKColor, error) {
 | 
					 | 
				
			||||||
	var c HSBKColor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if h < 0 || h > 360 {
 | 
					 | 
				
			||||||
		return c, errors.New("hue must be between 0.0-360.0")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if s < 0 || s > 1 {
 | 
					 | 
				
			||||||
		return c, errors.New("saturation must be between 0.0-1.0")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = HSBKColor{
 | 
					 | 
				
			||||||
		H: Float32Ptr(h),
 | 
					 | 
				
			||||||
		S: Float32Ptr(s),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewHSBColor(h, s, b float32) (HSBKColor, error) {
 | 
					 | 
				
			||||||
	var c HSBKColor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if h < 0 || h > 360 {
 | 
					 | 
				
			||||||
		return c, errors.New("hue must be between 0.0-360.0")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if s < 0 || s > 1 {
 | 
					 | 
				
			||||||
		return c, errors.New("saturation must be between 0.0-1.0")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if b < 0 || b > 1 {
 | 
					 | 
				
			||||||
		return c, errors.New("brightness must be between 0.0-1.0")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = HSBKColor{
 | 
					 | 
				
			||||||
		H: Float32Ptr(h),
 | 
					 | 
				
			||||||
		S: Float32Ptr(s),
 | 
					 | 
				
			||||||
		B: Float32Ptr(b),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewRed() (HSBKColor, error)    { return NewHSColor(HueRed, 1) }
 | 
					 | 
				
			||||||
func NewOrange() (HSBKColor, error) { return NewHSColor(HueOrange, 1) }
 | 
					 | 
				
			||||||
func NewYellow() (HSBKColor, error) { return NewHSColor(HueYellow, 1) }
 | 
					 | 
				
			||||||
func NewGreen() (HSBKColor, error)  { return NewHSColor(HueGreen, 1) }
 | 
					 | 
				
			||||||
func NewCyan() (HSBKColor, error)   { return NewHSColor(HueCyan, 1) }
 | 
					 | 
				
			||||||
func NewPurple() (HSBKColor, error) { return NewHSColor(HuePurple, 1) }
 | 
					 | 
				
			||||||
func NewPink() (HSBKColor, error)   { return NewHSColor(HuePink, 1) }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewWhite(k int16) (HSBKColor, error) {
 | 
					 | 
				
			||||||
	var c HSBKColor
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if k < 1500 || k > 9000 {
 | 
					 | 
				
			||||||
		return c, errors.New("kelvin must be between 1500-9000")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	c = HSBKColor{
 | 
					 | 
				
			||||||
		H: Float32Ptr(HueWhite),
 | 
					 | 
				
			||||||
		S: Float32Ptr(0.0),
 | 
					 | 
				
			||||||
		K: Int16Ptr(k),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return c, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func NewWhiteString(s string) (HSBKColor, error) {
 | 
					 | 
				
			||||||
	k, ok := DefaultWhites[s]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return HSBKColor{}, fmt.Errorf("'%s' is not a valid default white", s)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return NewWhite(int16(k))
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c RGBColor) ColorString() string {
 | 
					 | 
				
			||||||
	return fmt.Sprintf("rgb:%d,%d,%d", c.R, c.G, c.B)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c RGBColor) Hex() string {
 | 
					 | 
				
			||||||
	return fmt.Sprintf("#%x%x%x", c.R, c.G, c.B)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c HSBKColor) ColorString() string {
 | 
					 | 
				
			||||||
	var s []string
 | 
					 | 
				
			||||||
	if c.H != nil {
 | 
					 | 
				
			||||||
		s = append(s, fmt.Sprintf("hue:%g", *c.H))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if c.S != nil {
 | 
					 | 
				
			||||||
		s = append(s, fmt.Sprintf("saturation:%g", *c.S))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if c.B != nil {
 | 
					 | 
				
			||||||
		s = append(s, fmt.Sprintf("brightness:%g", *c.B))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if c.K != nil {
 | 
					 | 
				
			||||||
		s = append(s, fmt.Sprintf("kelvin:%d", *c.K))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return strings.Join(s, " ")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c HSBKColor) MarshalText() ([]byte, error) {
 | 
					 | 
				
			||||||
	return []byte(c.ColorString()), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c RGBColor) MarshalText() ([]byte, error) {
 | 
					 | 
				
			||||||
	return []byte(c.ColorString()), nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c NamedColor) ColorString() string {
 | 
					 | 
				
			||||||
	return string(c)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) ValidateColor(color Color) (Color, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    *HSBKColor
 | 
					 | 
				
			||||||
		r    *http.Response
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.validateColor(color); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	resp, err = NewResponse(r)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										35
									
								
								endpoints.go
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								endpoints.go
									
									
									
									
									
								
							@@ -1,35 +0,0 @@
 | 
				
			|||||||
package lifx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"net/url"
 | 
					 | 
				
			||||||
	"path"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func BuildURL(rawurl, rawpath string) string {
 | 
					 | 
				
			||||||
	u, _ := url.Parse(rawurl)
 | 
					 | 
				
			||||||
	u.Path = path.Join(u.Path, rawpath)
 | 
					 | 
				
			||||||
	return u.String()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					 | 
				
			||||||
	Endpoint      = "https://api.lifx.com/v1"
 | 
					 | 
				
			||||||
	EndpointState = func(selector string) string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, fmt.Sprintf("/lights/%s/state", selector))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	EndpointStateDelta = func(selector string) string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, fmt.Sprintf("/lights/%s/state/delta", selector))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	EndpointListLights = func(selector string) string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, fmt.Sprintf("/lights/%s", selector))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	EndpointStates = func() string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, "/lights/states")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	EndpointColor = func() string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, "/color")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	EndpointToggle = func(selector string) string {
 | 
					 | 
				
			||||||
		return BuildURL(Endpoint, fmt.Sprintf("/lights/%s/toggle", selector))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -3,6 +3,7 @@ module git.kill0.net/chill9/lume
 | 
				
			|||||||
go 1.15
 | 
					go 1.15
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
 | 
						git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef
 | 
				
			||||||
	github.com/BurntSushi/toml v0.3.1
 | 
						github.com/BurntSushi/toml v0.3.1
 | 
				
			||||||
	golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061
 | 
						golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef h1:8yyXAk+qiRvrowTeHHAOBZqGXXCr8SxWFydez61ZGp8=
 | 
				
			||||||
 | 
					git.kill0.net/chill9/lifx-go v0.0.0-20210215004437-f86c28b0a5ef/go.mod h1:ZFKIcwdJ4Nqlrkn/eUHbeLt0NVhFsfxBREkVoA+jzUc=
 | 
				
			||||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
					github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
				
			||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
					github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
 | 
					golang.org/x/sys v0.0.0-20210110051926-789bb1bd4061 h1:DQmQoKxQWtyybCtX/3dIuDBcAhFszqq8YiNeS6sNu1c=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										221
									
								
								lights.go
									
									
									
									
									
								
							
							
						
						
									
										221
									
								
								lights.go
									
									
									
									
									
								
							@@ -1,221 +0,0 @@
 | 
				
			|||||||
package lifx
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	//"crypto/tls"
 | 
					 | 
				
			||||||
	"encoding/json"
 | 
					 | 
				
			||||||
	"net/http"
 | 
					 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	OK       Status = "ok"
 | 
					 | 
				
			||||||
	TimedOut Status = "timed_out"
 | 
					 | 
				
			||||||
	Offline  Status = "offline"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type (
 | 
					 | 
				
			||||||
	Status string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Selector struct {
 | 
					 | 
				
			||||||
		Id   string `json:"id"`
 | 
					 | 
				
			||||||
		Name string `json:"name"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Product struct {
 | 
					 | 
				
			||||||
		Name         string       `json:"name"`
 | 
					 | 
				
			||||||
		Identifier   string       `json:"identifier"`
 | 
					 | 
				
			||||||
		Company      string       `json:"company"`
 | 
					 | 
				
			||||||
		Capabilities Capabilities `json:"capabilities"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Capabilities struct {
 | 
					 | 
				
			||||||
		HasColor             bool    `json:"has_color"`
 | 
					 | 
				
			||||||
		HasVariableColorTemp bool    `json:"has_variable_color_temp"`
 | 
					 | 
				
			||||||
		HasIR                bool    `json:"has_ir"`
 | 
					 | 
				
			||||||
		HasChain             bool    `json:"has_chain"`
 | 
					 | 
				
			||||||
		HasMultizone         bool    `json:"has_multizone"`
 | 
					 | 
				
			||||||
		MinKelvin            float64 `json:"min_kelvin"`
 | 
					 | 
				
			||||||
		MaxKelvin            float64 `json:"max_kelvin"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Light struct {
 | 
					 | 
				
			||||||
		Id              string    `json:"id"`
 | 
					 | 
				
			||||||
		UUID            string    `json:"uuid"`
 | 
					 | 
				
			||||||
		Label           string    `json:"label"`
 | 
					 | 
				
			||||||
		Connected       bool      `json:"connected"`
 | 
					 | 
				
			||||||
		Power           string    `json:"power"`
 | 
					 | 
				
			||||||
		Color           HSBKColor `json:"color"`
 | 
					 | 
				
			||||||
		Brightness      float64   `json:"brightness"`
 | 
					 | 
				
			||||||
		Effect          string    `json:"effect"`
 | 
					 | 
				
			||||||
		Group           Selector  `json:"group"`
 | 
					 | 
				
			||||||
		Location        Selector  `json:"location"`
 | 
					 | 
				
			||||||
		Product         Product   `json:"product"`
 | 
					 | 
				
			||||||
		LastSeen        time.Time `json:"last_seen"`
 | 
					 | 
				
			||||||
		SecondsLastSeen float64   `json:"seconds_last_seen"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	State struct {
 | 
					 | 
				
			||||||
		Power      string  `json:"power,omitempty"`
 | 
					 | 
				
			||||||
		Color      Color   `json:"color,omitempty"`
 | 
					 | 
				
			||||||
		Brightness float64 `json:"brightness,omitempty"`
 | 
					 | 
				
			||||||
		Duration   float64 `json:"duration,omitempty"`
 | 
					 | 
				
			||||||
		Infrared   float64 `json:"infrared,omitempty"`
 | 
					 | 
				
			||||||
		Fast       bool    `json:"fast,omitempty"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	StateDelta struct {
 | 
					 | 
				
			||||||
		Power      *string  `json:"power,omitempty"`
 | 
					 | 
				
			||||||
		Duration   *float64 `json:"duration,omitempty"`
 | 
					 | 
				
			||||||
		Infrared   *float64 `json:"infrared,omitempty"`
 | 
					 | 
				
			||||||
		Hue        *float64 `json:"hue,omitempty"`
 | 
					 | 
				
			||||||
		Saturation *float64 `json:"saturation,omitempty"`
 | 
					 | 
				
			||||||
		Brightness *float64 `json:"brightness,omitempty"`
 | 
					 | 
				
			||||||
		Kelvin     *int     `json:"kelvin,omitempty"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	StateWithSelector struct {
 | 
					 | 
				
			||||||
		State
 | 
					 | 
				
			||||||
		Selector string `json:"selector"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	States struct {
 | 
					 | 
				
			||||||
		States   []StateWithSelector `json:"states,omitempty"`
 | 
					 | 
				
			||||||
		Defaults State               `json:"defaults,omitempty"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	Toggle struct {
 | 
					 | 
				
			||||||
		Duration float64 `json:"duration,omitempty"`
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) SetState(selector string, state State) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    *LifxResponse
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.setState(selector, state); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp.IsError() {
 | 
					 | 
				
			||||||
		return nil, resp.GetLifxError()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if state.Fast && resp.StatusCode == http.StatusAccepted {
 | 
					 | 
				
			||||||
		return nil, nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) FastSetState(selector string, state State) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	state.Fast = true
 | 
					 | 
				
			||||||
	return c.SetState(selector, state)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) SetStates(selector string, states States) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    *LifxResponse
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.setStates(selector, states); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) StateDelta(selector string, delta StateDelta) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    *LifxResponse
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.stateDelta(selector, delta); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) Toggle(selector string, duration float64) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    *LifxResponse
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.toggle(selector, duration); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp.IsError() {
 | 
					 | 
				
			||||||
		return nil, resp.GetLifxError()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) ListLights(selector string) ([]Light, error) {
 | 
					 | 
				
			||||||
	var (
 | 
					 | 
				
			||||||
		err  error
 | 
					 | 
				
			||||||
		s    []Light
 | 
					 | 
				
			||||||
		resp *Response
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp, err = c.listLights(selector); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	defer resp.Body.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if resp.StatusCode > 299 {
 | 
					 | 
				
			||||||
		return nil, resp.GetLifxError()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if err = json.NewDecoder(resp.Body).Decode(&s); err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return s, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) PowerOff(selector string) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	return c.SetState(selector, State{Power: "off"})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) FastPowerOff(selector string) {
 | 
					 | 
				
			||||||
	c.SetState(selector, State{Power: "off", Fast: true})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) PowerOn(selector string) (*LifxResponse, error) {
 | 
					 | 
				
			||||||
	return c.SetState(selector, State{Power: "on"})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (c *Client) FastPowerOn(selector string) {
 | 
					 | 
				
			||||||
	c.SetState(selector, State{Power: "on", Fast: true})
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Reference in New Issue
	
	Block a user