Merge branch 'asmodeus' of git.aiterp.net:lucifer/new-server into asmodeus

This commit is contained in:
Stian Fredrik Aune
2021-05-23 14:00:51 +02:00
12 changed files with 982 additions and 47 deletions
+18 -16
View File
@@ -2,14 +2,15 @@ package models
import (
"fmt"
"regexp"
"math"
"strconv"
"strings"
)
type ColorValue struct {
Hue int `json:"h,omitempty"`
Saturation int `json:"s,omitempty"`
Kelvin int `json:"kelvin,omitempty"`
Hue float64 `json:"h,omitempty"` // 0..360
Saturation float64 `json:"s,omitempty"` // 0..=1
Kelvin int `json:"kelvin,omitempty"`
}
func (c *ColorValue) IsHueSat() bool {
@@ -25,16 +26,17 @@ func (c *ColorValue) String() string {
return fmt.Sprintf("kelvin:%d", c.Kelvin)
}
return fmt.Sprintf("hsv:%d,%d", c.Hue, c.Saturation)
return fmt.Sprintf("hsv:%f,%f", c.Hue, c.Saturation)
}
var kelvinRegex = regexp.MustCompile("kelvin:([0-9]+)")
var hsRegex = regexp.MustCompile("hs:([0-9]+),([0-9]+)")
func ParseColorValue(raw string) (ColorValue, error) {
if kelvinRegex.MatchString(raw) {
part := kelvinRegex.FindString(raw)
parsedPart, err := strconv.Atoi(part)
tokens := strings.SplitN(raw, ":", 2)
if len(tokens) != 2 {
return ColorValue{}, ErrBadInput
}
if tokens[0] == "kelvin" {
parsedPart, err := strconv.Atoi(tokens[1])
if err != nil {
return ColorValue{}, ErrBadInput
}
@@ -42,19 +44,19 @@ func ParseColorValue(raw string) (ColorValue, error) {
return ColorValue{Kelvin: parsedPart}, nil
}
if hsRegex.MatchString(raw) {
parts := kelvinRegex.FindAllString(raw, 2)
if tokens[0] == "hs" {
parts := strings.Split(tokens[1], ",")
if len(parts) < 2 {
return ColorValue{}, ErrUnknownColorFormat
}
part1, err1 := strconv.Atoi(parts[0])
part2, err2 := strconv.Atoi(parts[1])
part1, err1 := strconv.ParseFloat(parts[0], 64)
part2, err2 := strconv.ParseFloat(parts[1], 64)
if err1 != nil || err2 != nil {
return ColorValue{}, ErrBadInput
}
return ColorValue{Hue: part1, Saturation: part2}, nil
return ColorValue{Hue: math.Mod(part1, 360), Saturation: math.Min(math.Max(part2, 0), 1)}, nil
}
return ColorValue{}, ErrUnknownColorFormat
+3 -3
View File
@@ -22,13 +22,13 @@ type Device struct {
// DeviceState contains optional state values that
// - Power: Whether the device is powered on
// - Color: Color value, if a color setting can be set on the device
// - Intensity: e.g. brightness, from 0-255
// - Intensity: e.g. brightness, range 0..=1
// - Temperature: e.g. for thermostats
type DeviceState struct {
Power bool `json:"power"`
Color ColorValue `json:"color,omitempty"`
Intensity int `json:"intensity,omitempty"`
Temperature int `json:"temperature"`
Intensity float64 `json:"intensity,omitempty"`
Temperature float64 `json:"temperature"`
}
type NewDeviceState struct {
+2 -1
View File
@@ -12,6 +12,7 @@ type DriverProvider interface {
type Driver interface {
SearchBridge(ctx context.Context, address string, dryRun bool) ([]Bridge, error)
SearchDevices(ctx context.Context, bridge Bridge, timeout time.Duration) ([]Device, error)
Consume(ctx context.Context, bridge Bridge, devices []Device, ch chan Event) (chan<- struct{}, error)
ListDevices(ctx context.Context, bridge Bridge) ([]Device, error)
Publish(ctx context.Context, bridge Bridge, devices []Device) error
Run(ctx context.Context, bridge Bridge, ch chan<- Event) error
}
+5
View File
@@ -8,3 +8,8 @@ var ErrBadInput = errors.New("bad input")
var ErrBadColor = errors.New("bad color")
var ErrInternal = errors.New("internal")
var ErrUnknownColorFormat = errors.New("unknown color format")
var ErrMissingToken = errors.New("driver is missing authentication information")
var ErrIncorrectToken = errors.New("driver is not accepting authentication information")
var ErrUnexpectedResponse = errors.New("driver api returned unexpected response (wrong driver selected?)")
var ErrBridgeSearchFailed = errors.New("bridge search failed")
+2 -2
View File
@@ -72,9 +72,9 @@ func (c *EventCondition) checkDevice(key string, device Device) bool {
case "color":
return c.matches(device.State.Color.String())
case "intensity":
return c.matches(strconv.Itoa(device.State.Intensity))
return c.matches(strconv.FormatFloat(device.State.Intensity, 'f', -1, 64))
case "temperature":
return c.matches(strconv.Itoa(device.State.Temperature))
return c.matches(strconv.FormatFloat(device.State.Temperature, 'f', -1, 64))
}
return false