Files
new-server/models/device.go
T

181 lines
4.5 KiB
Go
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package models
import (
"context"
"strings"
)
type Device struct {
ID int `json:"id"`
BridgeID int `json:"bridgeID"`
InternalID string `json:"internalId"`
Icon string `json:"icon"`
Name string `json:"name"`
Capabilities []DeviceCapability `json:"capabilities"`
ButtonNames []string `json:"buttonNames"`
DriverProperties map[string]interface{} `json:"driverProperties"`
UserProperties map[string]string `json:"userProperties"`
State DeviceState `json:"state"`
Tags []string `json:"tags"`
}
type DeviceUpdate struct {
Icon *string `json:"icon"`
Name *string `json:"name"`
UserProperties map[string]*string `json:"userProperties"`
}
// 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, range 0..=1
// - Temperature: e.g. for thermostats
type DeviceState struct {
Power bool `json:"power"`
Color ColorValue `json:"color,omitempty"`
Intensity float64 `json:"intensity,omitempty"`
Temperature float64 `json:"temperature"`
}
type NewDeviceState struct {
Power *bool `json:"power"`
Color *string `json:"color"`
Intensity *float64 `json:"intensity"`
Temperature *int `json:"temperature"`
}
type DeviceCapability string
type SaveMode int
const (
SMState SaveMode = 1
SMProperties SaveMode = 2
SMTags SaveMode = 4
)
type DeviceRepository interface {
Find(ctx context.Context, id int) (*Device, error)
FetchByReference(ctx context.Context, kind ReferenceKind, value string) ([]Device, error)
Save(ctx context.Context, device *Device, mode SaveMode) error
Delete(ctx context.Context, device *Device) error
}
func DeviceCapabilitiesToStrings(caps []DeviceCapability) []string {
res := make([]string, 0, len(caps))
for _, cap := range caps {
res = append(res, string(cap))
}
return res
}
var (
DCPower DeviceCapability = "Power"
DCColorHS DeviceCapability = "ColorHS"
DCColorHSK DeviceCapability = "ColorHSK"
DCColorKelvin DeviceCapability = "ColorKelvin"
DCButtons DeviceCapability = "Buttons"
DCPresence DeviceCapability = "Presence"
DCIntensity DeviceCapability = "Intensity"
DCTemperatureControl DeviceCapability = "TemperatureControl"
DCTemperatureSensor DeviceCapability = "TemperatureSensor"
)
var Capabilities = []DeviceCapability{
DCPower,
DCColorHS,
DCColorKelvin,
DCButtons,
DCPresence,
DCIntensity,
DCTemperatureControl,
DCTemperatureSensor,
}
func (d *Device) ApplyUpdate(update DeviceUpdate) {
if update.Name != nil {
d.Name = *update.Name
}
if update.Icon != nil {
d.Icon = *update.Icon
}
if d.UserProperties == nil {
d.UserProperties = make(map[string]string)
}
for key, value := range update.UserProperties {
if value != nil {
d.UserProperties[key] = *value
} else {
delete(d.UserProperties, key)
}
}
}
func (d *Device) Validate() error {
d.Name = strings.Trim(d.Name, " \t\n ")
if d.Name == "" {
return ErrInvalidName
}
newCaps := make([]DeviceCapability, 0, len(d.Capabilities))
for _, currCap := range d.Capabilities {
for _, validCap := range Capabilities {
if currCap == validCap {
newCaps = append(newCaps, currCap)
break
}
}
}
d.Capabilities = newCaps
return nil
}
func (d *Device) HasTag(tags ...string) bool {
for _, c := range d.Tags {
for _, c2 := range tags {
if c == c2 {
return true
}
}
}
return false
}
func (d *Device) HasCapability(capabilities ...DeviceCapability) bool {
for _, c := range d.Capabilities {
for _, c2 := range capabilities {
if c == c2 {
return true
}
}
}
return false
}
func (d *Device) SetState(newState NewDeviceState) error {
if newState.Power != nil && d.HasCapability(DCPower) {
d.State.Power = *newState.Power
}
if newState.Color != nil {
parsed, err := ParseColorValue(*newState.Color)
if err != nil {
return err
}
if (parsed.IsKelvin() && d.HasCapability(DCColorKelvin, DCColorHSK)) || (parsed.IsHueSat() && d.HasCapability(DCColorHS)) {
d.State.Color = parsed
}
}
if newState.Intensity != nil && d.HasCapability(DCIntensity) {
d.State.Intensity = *newState.Intensity
}
return nil
}