You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
172 lines
4.3 KiB
172 lines
4.3 KiB
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 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) 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
|
|
}
|