refactor color system to be separate from models, also move errors out of models.
continuous-integration/drone/push Build is passing
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"io"
|
||||
@@ -159,7 +160,7 @@ func (b *Bridge) ForgetDevice(ctx context.Context, device models.Device) error {
|
||||
}
|
||||
b.mu.Unlock()
|
||||
if !found {
|
||||
return models.ErrNotFound
|
||||
return lerrors.ErrNotFound
|
||||
}
|
||||
|
||||
// Delete light from bridge
|
||||
@@ -237,7 +238,7 @@ func (b *Bridge) getToken(ctx context.Context) (string, error) {
|
||||
return "", errLinkButtonNotPressed
|
||||
}
|
||||
if result[0].Success == nil {
|
||||
return "", models.ErrUnexpectedResponse
|
||||
return "", lerrors.ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
return result[0].Success.Username, nil
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"log"
|
||||
"net/http"
|
||||
@@ -22,7 +23,7 @@ type Driver struct {
|
||||
func (d *Driver) SearchBridge(ctx context.Context, address, _ string, dryRun bool) ([]models.Bridge, error) {
|
||||
if address == "" {
|
||||
if !dryRun {
|
||||
return nil, models.ErrAddressOnlyDryRunnable
|
||||
return nil, lerrors.ErrAddressOnlyDryRunnable
|
||||
}
|
||||
|
||||
res, err := http.Get("https://discovery.meethue.com")
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/color"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"golang.org/x/sync/errgroup"
|
||||
"log"
|
||||
@@ -283,7 +284,6 @@ func (b *Bridge) MakeCongruent(ctx context.Context) (int, error) {
|
||||
} else if xyColor, ok := device.State.Color.ToXY(); ok && light.Color != nil {
|
||||
xy := light.Color.Gamut.Conform(*xyColor.XY).Round()
|
||||
if xy.DistanceTo(light.Color.XY) > 0.0009 || (light.ColorTemperature != nil && light.ColorTemperature.Mirek != nil) {
|
||||
log.Println(xyColor.String(), device.State.Color.String())
|
||||
update.ColorXY = &xy
|
||||
changed = true
|
||||
}
|
||||
@@ -428,7 +428,7 @@ func (b *Bridge) GenerateDevices() []models.Device {
|
||||
}
|
||||
if light.Color != nil {
|
||||
if device.State.Color.IsEmpty() {
|
||||
device.State.Color = models.ColorValue{
|
||||
device.State.Color = color.Color{
|
||||
XY: &light.Color.XY,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
@@ -52,7 +52,7 @@ func (c *Client) Register(ctx context.Context) (string, error) {
|
||||
}
|
||||
}
|
||||
if result[0].Success == nil {
|
||||
return "", models.ErrUnexpectedResponse
|
||||
return "", lerrors.ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
c.token = result[0].Success.Username
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"git.aiterp.net/lucifer/new-server/internal/color"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -152,9 +152,9 @@ type LightDimming struct {
|
||||
}
|
||||
|
||||
type LightColor struct {
|
||||
Gamut models.ColorGamut `json:"gamut"`
|
||||
GamutType string `json:"gamut_type"`
|
||||
XY models.ColorXY `json:"xy"`
|
||||
Gamut color.Gamut `json:"gamut"`
|
||||
GamutType string `json:"gamut_type"`
|
||||
XY color.XY `json:"xy"`
|
||||
}
|
||||
|
||||
type LightCT struct {
|
||||
@@ -182,7 +182,7 @@ type LightAlert struct {
|
||||
type ResourceUpdate struct {
|
||||
Name *string
|
||||
Power *bool
|
||||
ColorXY *models.ColorXY
|
||||
ColorXY *color.XY
|
||||
Brightness *float64
|
||||
Mirek *int
|
||||
TransitionDuration *time.Duration
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -19,7 +20,7 @@ type Driver struct {
|
||||
func (d *Driver) SearchBridge(ctx context.Context, address, token string, dryRun bool) ([]models.Bridge, error) {
|
||||
if address == "" {
|
||||
if !dryRun {
|
||||
return nil, models.ErrAddressOnlyDryRunnable
|
||||
return nil, lerrors.ErrAddressOnlyDryRunnable
|
||||
}
|
||||
|
||||
res, err := http.Get("https://discovery.meethue.com")
|
||||
|
||||
@@ -2,6 +2,8 @@ package lifx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"git.aiterp.net/lucifer/new-server/internal/color"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"log"
|
||||
"sync"
|
||||
@@ -20,7 +22,7 @@ type Bridge struct {
|
||||
func (b *Bridge) StartSearch(ctx context.Context) error {
|
||||
c := b.getClient()
|
||||
if c == nil {
|
||||
return models.ErrBridgeRunningRequired
|
||||
return lerrors.ErrBridgeRunningRequired
|
||||
}
|
||||
|
||||
_, err := c.HorribleBroadcast(ctx, &GetService{})
|
||||
@@ -129,9 +131,9 @@ func (b *Bridge) Run(ctx context.Context, debug bool) error {
|
||||
|
||||
for {
|
||||
target, seq, payload, err := client.Recv(time.Millisecond * 200)
|
||||
if err == models.ErrInvalidPacketSize || err == models.ErrPayloadTooShort || err == models.ErrUnrecognizedPacketType {
|
||||
if err == lerrors.ErrInvalidPacketSize || err == lerrors.ErrPayloadTooShort || err == lerrors.ErrUnrecognizedPacketType {
|
||||
log.Println("LIFX udp socket received something weird:", err)
|
||||
} else if err != nil && err != models.ErrReadTimeout {
|
||||
} else if err != nil && err != lerrors.ErrReadTimeout {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
@@ -168,8 +170,8 @@ func (b *Bridge) Run(ctx context.Context, debug bool) error {
|
||||
if state.deviceState == nil {
|
||||
state.deviceState = &models.DeviceState{
|
||||
Power: p.On,
|
||||
Color: models.ColorValue{
|
||||
HS: &models.ColorHS{
|
||||
Color: color.Color{
|
||||
HS: &color.HueSat{
|
||||
Hue: p.Hue,
|
||||
Sat: p.Sat,
|
||||
},
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
@@ -215,7 +215,7 @@ func (c *Client) Recv(timeout time.Duration) (target string, seq uint8, payload
|
||||
}
|
||||
if err != nil {
|
||||
if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
|
||||
err = models.ErrReadTimeout
|
||||
err = lerrors.ErrReadTimeout
|
||||
return
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ func (c *Client) Recv(timeout time.Duration) (target string, seq uint8, payload
|
||||
|
||||
packet := Packet(c.buf[:n])
|
||||
if n < 2 || packet.Size() != n && packet.Protocol() != 1024 {
|
||||
err = models.ErrInvalidAddress
|
||||
err = lerrors.ErrInvalidAddress
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package lifx
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"log"
|
||||
"net"
|
||||
)
|
||||
@@ -60,7 +60,7 @@ func (p *Packet) SetTarget(v string) error {
|
||||
return err
|
||||
}
|
||||
if len(addr) != 6 {
|
||||
return models.ErrInvalidAddress
|
||||
return lerrors.ErrInvalidAddress
|
||||
}
|
||||
|
||||
copy((*p)[8:], addr)
|
||||
@@ -133,7 +133,7 @@ func (p *Packet) Payload() (res Payload, err error) {
|
||||
res = &SetLightPower{}
|
||||
err = res.Decode((*p)[36:])
|
||||
default:
|
||||
err = models.ErrUnrecognizedPacketType
|
||||
err = lerrors.ErrUnrecognizedPacketType
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -3,7 +3,7 @@ package lifx
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"math"
|
||||
"time"
|
||||
)
|
||||
@@ -82,7 +82,7 @@ type StateHostFirmware struct {
|
||||
|
||||
func (p *StateHostFirmware) Decode(data []byte) error {
|
||||
if len(data) < 20 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
ts := int64(binary.LittleEndian.Uint64(data[0:8]))
|
||||
@@ -123,7 +123,7 @@ type StateVersion struct {
|
||||
|
||||
func (p *StateVersion) Decode(data []byte) error {
|
||||
if len(data) < 8 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
p.Vendor = binary.LittleEndian.Uint32(data[0:4])
|
||||
@@ -207,7 +207,7 @@ type SetColor struct {
|
||||
|
||||
func (p *SetColor) Decode(data []byte) error {
|
||||
if len(data) < 13 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
hue := binary.LittleEndian.Uint16(data[1:3])
|
||||
@@ -263,7 +263,7 @@ type SetLightPower struct {
|
||||
|
||||
func (p *SetLightPower) Decode(data []byte) error {
|
||||
if len(data) < 6 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
level := binary.LittleEndian.Uint16(data[0:2])
|
||||
@@ -314,7 +314,7 @@ func (p *StateService) String() string {
|
||||
|
||||
func (p *StateService) Decode(data []byte) error {
|
||||
if len(data) < 5 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
p.Service = int(data[0])
|
||||
@@ -357,7 +357,7 @@ func (p *LightState) String() string {
|
||||
|
||||
func (p *LightState) Decode(data []byte) error {
|
||||
if len(data) < 52 {
|
||||
return models.ErrPayloadTooShort
|
||||
return lerrors.ErrPayloadTooShort
|
||||
}
|
||||
|
||||
hue := binary.LittleEndian.Uint16(data[0:2])
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lifx
|
||||
|
||||
import (
|
||||
"git.aiterp.net/lucifer/new-server/internal/color"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"math"
|
||||
"time"
|
||||
@@ -38,7 +39,7 @@ func (s *State) generateUpdate() []Payload {
|
||||
|
||||
c, ok := s.deviceState.Color.ToHSK()
|
||||
if !ok {
|
||||
c, _ = models.ParseColorValue("hsk:0,0,4000")
|
||||
c, _ = color.Parse("hsk:0,0,4000")
|
||||
}
|
||||
|
||||
l := s.lightState
|
||||
@@ -76,16 +77,16 @@ func (s *State) handleAck(seq uint8) {
|
||||
prevLabel = s.lightState.Label
|
||||
}
|
||||
|
||||
color, ok := s.deviceState.Color.ToHSK()
|
||||
c, ok := s.deviceState.Color.ToHSK()
|
||||
if !ok {
|
||||
color, _ = models.ParseColorValue("hsk:0,0,4000")
|
||||
c, _ = color.Parse("hsk:0,0,4000")
|
||||
}
|
||||
|
||||
s.lightState = &LightState{
|
||||
Hue: color.HS.Hue,
|
||||
Sat: color.HS.Sat,
|
||||
Hue: c.HS.Hue,
|
||||
Sat: c.HS.Sat,
|
||||
Bri: s.deviceState.Intensity,
|
||||
Kelvin: *color.K,
|
||||
Kelvin: *c.K,
|
||||
On: s.deviceState.Power,
|
||||
Label: prevLabel,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"io"
|
||||
"log"
|
||||
@@ -163,9 +164,9 @@ func (b *bridge) command(ctx context.Context, command string, payload interface{
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return models.ErrCannotForwardRequest
|
||||
return lerrors.ErrCannotForwardRequest
|
||||
} else if res.StatusCode != 200 {
|
||||
return models.ErrIncorrectToken
|
||||
return lerrors.ErrIncorrectToken
|
||||
}
|
||||
|
||||
if target == nil {
|
||||
@@ -174,7 +175,7 @@ func (b *bridge) command(ctx context.Context, command string, payload interface{
|
||||
|
||||
err = json.NewDecoder(res.Body).Decode(&target)
|
||||
if err != nil {
|
||||
return models.ErrUnexpectedResponse
|
||||
return lerrors.ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -190,27 +191,27 @@ func (b *bridge) authenticate(ctx context.Context) error {
|
||||
Password: b.password,
|
||||
})
|
||||
if err != nil {
|
||||
return models.ErrMissingToken
|
||||
return lerrors.ErrMissingToken
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", accountEndpoint + "login", bytes.NewReader(body))
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", accountEndpoint+"login", bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return models.ErrMissingToken
|
||||
return lerrors.ErrMissingToken
|
||||
}
|
||||
|
||||
addDefaultHeaders(req)
|
||||
|
||||
res, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return models.ErrCannotForwardRequest
|
||||
return lerrors.ErrCannotForwardRequest
|
||||
} else if res.StatusCode != 200 {
|
||||
return models.ErrIncorrectToken
|
||||
return lerrors.ErrIncorrectToken
|
||||
}
|
||||
|
||||
var resBody authResBody
|
||||
err = json.NewDecoder(res.Body).Decode(&resBody)
|
||||
if err != nil {
|
||||
return models.ErrBridgeSearchFailed
|
||||
return lerrors.ErrBridgeSearchFailed
|
||||
}
|
||||
|
||||
log.Printf("Mill: Authenticated as %s", resBody.NickName)
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/color"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"github.com/lucasb-eyer/go-colorful"
|
||||
"io"
|
||||
@@ -70,7 +72,7 @@ func (b *bridge) Devices() []models.Device {
|
||||
UserProperties: nil,
|
||||
State: models.DeviceState{
|
||||
Power: panel.ColorRGBA[3] == 0,
|
||||
Color: models.ColorValue{RGB: &models.ColorRGB{
|
||||
Color: color.Color{RGB: &color.RGB{
|
||||
Red: rgb.R,
|
||||
Green: rgb.G,
|
||||
Blue: rgb.B,
|
||||
@@ -140,9 +142,9 @@ func (b *bridge) Overview(ctx context.Context) (*Overview, error) {
|
||||
|
||||
switch res.StatusCode {
|
||||
case 400, 403, 500, 503:
|
||||
return nil, models.ErrUnexpectedResponse
|
||||
return nil, lerrors.ErrUnexpectedResponse
|
||||
case 401:
|
||||
return nil, models.ErrIncorrectToken
|
||||
return nil, lerrors.ErrIncorrectToken
|
||||
}
|
||||
|
||||
overview := Overview{}
|
||||
@@ -333,7 +335,7 @@ func (b *bridge) updateEffect(ctx context.Context) error {
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 204 {
|
||||
return models.ErrUnexpectedResponse
|
||||
return lerrors.ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
b.mu.Lock()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
"net/http"
|
||||
"sync"
|
||||
@@ -30,7 +31,7 @@ func (d *Driver) SearchBridge(ctx context.Context, address, _ string, dryRun boo
|
||||
return nil, err
|
||||
}
|
||||
if deviceInfo.ModelNumber == "" {
|
||||
return nil, models.ErrUnexpectedResponse
|
||||
return nil, lerrors.ErrUnexpectedResponse
|
||||
}
|
||||
|
||||
token := ""
|
||||
@@ -47,7 +48,7 @@ func (d *Driver) SearchBridge(ctx context.Context, address, _ string, dryRun boo
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return nil, models.ErrBridgeSearchFailed
|
||||
return nil, lerrors.ErrBridgeSearchFailed
|
||||
}
|
||||
|
||||
tokenResponse := TokenResponse{}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
package drivers
|
||||
|
||||
import "git.aiterp.net/lucifer/new-server/models"
|
||||
import (
|
||||
"git.aiterp.net/lucifer/new-server/internal/lerrors"
|
||||
"git.aiterp.net/lucifer/new-server/models"
|
||||
)
|
||||
|
||||
type DriverMap map[models.DriverKind]models.Driver
|
||||
|
||||
func (m DriverMap) Provide(kind models.DriverKind) (models.Driver, error) {
|
||||
if m[kind] == nil {
|
||||
return nil, models.ErrUnknownDriver
|
||||
return nil, lerrors.ErrUnknownDriver
|
||||
}
|
||||
|
||||
return m[kind], nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user