This commit is contained in:
+13
-11
@@ -7,17 +7,18 @@ import (
|
||||
)
|
||||
|
||||
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"`
|
||||
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"`
|
||||
SceneAssignments []DeviceSceneAssignment `json:"sceneAssignments"`
|
||||
State DeviceState `json:"state"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
type DeviceUpdate struct {
|
||||
@@ -66,6 +67,7 @@ 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
|
||||
SaveMany(ctx context.Context, mode SaveMode, devices []Device) error
|
||||
Delete(ctx context.Context, device *Device) error
|
||||
}
|
||||
|
||||
|
||||
+53
-12
@@ -1,10 +1,12 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Scene struct {
|
||||
@@ -54,15 +56,16 @@ func (s *Scene) RoleIndex(device *Device) int {
|
||||
type SceneEffect string
|
||||
|
||||
const (
|
||||
SEStatic SceneEffect = "Plain"
|
||||
SERandom SceneEffect = "Random"
|
||||
SEGradient SceneEffect = "Gradient"
|
||||
SETransition SceneEffect = "Transition"
|
||||
SEStatic SceneEffect = "Plain"
|
||||
SERandom SceneEffect = "Random"
|
||||
SEGradient SceneEffect = "Gradient"
|
||||
SEWalkingGradient SceneEffect = "WalkingGradient"
|
||||
SETransition SceneEffect = "Transition"
|
||||
)
|
||||
|
||||
type SceneRole struct {
|
||||
Effect SceneEffect `json:"effect"`
|
||||
PowerMode ScenePowerMode `json:"overridePower"`
|
||||
PowerMode ScenePowerMode `json:"powerMode"`
|
||||
TargetKind ReferenceKind `json:"targetKind"`
|
||||
TargetValue string `json:"targetValue"`
|
||||
Interpolate bool `json:"interpolate"`
|
||||
@@ -70,6 +73,34 @@ type SceneRole struct {
|
||||
States []NewDeviceState `json:"states"`
|
||||
}
|
||||
|
||||
type SceneRunContext struct {
|
||||
Index int
|
||||
Length int
|
||||
IntervalNumber int64
|
||||
IntervalMax int64
|
||||
}
|
||||
|
||||
func (d *SceneRunContext) PositionFacShifted() float64 {
|
||||
shiftFac := float64((int64(d.Index)+d.IntervalNumber)%int64(d.Length)) * (1 / float64(d.Length))
|
||||
|
||||
return math.Mod(d.PositionFac()+shiftFac, 1)
|
||||
}
|
||||
|
||||
func (d *SceneRunContext) PositionFac() float64 {
|
||||
return float64(d.Index) / float64(d.Length)
|
||||
}
|
||||
|
||||
func (d *SceneRunContext) IntervalFac() float64 {
|
||||
fac := float64(d.IntervalNumber) / float64(d.IntervalMax)
|
||||
if fac > 1 {
|
||||
return 1
|
||||
} else if fac < 0 {
|
||||
return 0
|
||||
} else {
|
||||
return fac
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SceneRole) Validate() error {
|
||||
if len(r.States) == 0 {
|
||||
return ErrSceneRoleNoStates
|
||||
@@ -134,16 +165,18 @@ func (r *SceneRole) ApplyOrder(devices []Device) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *SceneRole) ApplyEffect(device *Device, intervalFac float64, positionFac float64) (newState NewDeviceState, deviceChanged bool) {
|
||||
func (r *SceneRole) ApplyEffect(device *Device, c SceneRunContext) (newState NewDeviceState, deviceChanged bool) {
|
||||
switch r.Effect {
|
||||
case SEStatic:
|
||||
newState = r.States[0]
|
||||
case SERandom:
|
||||
newState = r.State(rand.Float64())
|
||||
case SEGradient:
|
||||
newState = r.State(positionFac)
|
||||
newState = r.State(c.PositionFac())
|
||||
case SEWalkingGradient:
|
||||
newState = r.State(c.PositionFacShifted())
|
||||
case SETransition:
|
||||
newState = r.State(intervalFac)
|
||||
newState = r.State(c.IntervalFac())
|
||||
}
|
||||
|
||||
switch r.PowerMode {
|
||||
@@ -196,9 +229,17 @@ const (
|
||||
SPOverride ScenePowerMode = "Override" // Same as above, but Scene state set Device state' power. This is good for "wake up" scenes.
|
||||
)
|
||||
|
||||
type SceneAssignment struct {
|
||||
Scene *Scene
|
||||
Device *Device
|
||||
Tag string
|
||||
// DeviceSceneAssignment is an entry on the device stack.
|
||||
type DeviceSceneAssignment struct {
|
||||
SceneID int `json:"sceneId"`
|
||||
Group string `json:"group"`
|
||||
StartTime time.Time `json:"start"`
|
||||
DurationMS int64 `json:"durationMs"`
|
||||
}
|
||||
|
||||
type SceneRepository interface {
|
||||
Find(ctx context.Context, id int) (*Scene, error)
|
||||
FetchAll(ctx context.Context) ([]Scene, error)
|
||||
Save(ctx context.Context, bridge *Scene) error
|
||||
Delete(ctx context.Context, bridge *Scene) error
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user