|
|
@ -61,24 +61,38 @@ const ( |
|
|
|
SEGradient SceneEffect = "Gradient" |
|
|
|
SEWalkingGradient SceneEffect = "WalkingGradient" |
|
|
|
SETransition SceneEffect = "Transition" |
|
|
|
SEMotion SceneEffect = "Motion" |
|
|
|
SETemperature SceneEffect = "Temperature" |
|
|
|
) |
|
|
|
|
|
|
|
type SceneRole struct { |
|
|
|
Effect SceneEffect `json:"effect"` |
|
|
|
PowerMode ScenePowerMode `json:"powerMode"` |
|
|
|
TargetKind ReferenceKind `json:"targetKind"` |
|
|
|
TargetValue string `json:"targetValue"` |
|
|
|
Interpolate bool `json:"interpolate"` |
|
|
|
Relative bool `json:"relative"` |
|
|
|
Order string `json:"order"` |
|
|
|
States []NewDeviceState `json:"states"` |
|
|
|
Effect SceneEffect `json:"effect"` |
|
|
|
MotionSeconds float64 `json:"motionSeconds"` |
|
|
|
MinTemperature int `json:"minTemperature"` |
|
|
|
MaxTemperature int `json:"maxTemperature"` |
|
|
|
PowerMode ScenePowerMode `json:"powerMode"` |
|
|
|
TargetKind ReferenceKind `json:"targetKind"` |
|
|
|
TargetValue string `json:"targetValue"` |
|
|
|
Interpolate bool `json:"interpolate"` |
|
|
|
Relative bool `json:"relative"` |
|
|
|
Order string `json:"order"` |
|
|
|
States []NewDeviceState `json:"states"` |
|
|
|
} |
|
|
|
|
|
|
|
type SceneRunContext struct { |
|
|
|
CurrentTime time.Time |
|
|
|
Index int |
|
|
|
Length int |
|
|
|
IntervalNumber int64 |
|
|
|
IntervalMax int64 |
|
|
|
Sensors []SceneSensor |
|
|
|
} |
|
|
|
|
|
|
|
type SceneSensor struct { |
|
|
|
ID int |
|
|
|
UpdateTime time.Time |
|
|
|
Temperature *float64 |
|
|
|
Presence *bool |
|
|
|
} |
|
|
|
|
|
|
|
func (d *SceneRunContext) PositionFacShifted() float64 { |
|
|
@ -120,7 +134,7 @@ func (r *SceneRole) Validate() error { |
|
|
|
} |
|
|
|
|
|
|
|
switch r.Effect { |
|
|
|
case SEStatic, SERandom, SEGradient, SEWalkingGradient, SETransition: |
|
|
|
case SEStatic, SERandom, SEGradient, SEWalkingGradient, SETransition, SEMotion, SETemperature: |
|
|
|
default: |
|
|
|
return ErrSceneRoleUnknownEffect |
|
|
|
} |
|
|
@ -178,6 +192,53 @@ func (r *SceneRole) ApplyEffect(device *Device, c SceneRunContext) (newState New |
|
|
|
newState = r.State(c.PositionFacShifted()) |
|
|
|
case SETransition: |
|
|
|
newState = r.State(c.IntervalFac()) |
|
|
|
case SEMotion: |
|
|
|
presence := false |
|
|
|
absenceTime := time.Time{} |
|
|
|
|
|
|
|
for _, sensors := range c.Sensors { |
|
|
|
if sensors.Presence == nil { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
if *sensors.Presence { |
|
|
|
presence = true |
|
|
|
} else { |
|
|
|
if sensors.UpdateTime.After(absenceTime) { |
|
|
|
absenceTime = sensors.UpdateTime |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if presence { |
|
|
|
newState = r.State(0.0) |
|
|
|
} else { |
|
|
|
fac := c.CurrentTime.Sub(absenceTime).Seconds() / r.MotionSeconds |
|
|
|
if fac < 0 { |
|
|
|
fac = 0 |
|
|
|
} else if fac > 1 { |
|
|
|
fac = 1 |
|
|
|
} |
|
|
|
|
|
|
|
newState = r.State(fac) |
|
|
|
} |
|
|
|
case SETemperature: |
|
|
|
avg := 0.0 |
|
|
|
count := 0 |
|
|
|
|
|
|
|
for _, sensor := range c.Sensors { |
|
|
|
if sensor.Temperature == nil { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
if count == 0 { |
|
|
|
avg = *sensor.Temperature |
|
|
|
count = 1 |
|
|
|
} else { |
|
|
|
avg = ((avg * float64(count)) + *sensor.Temperature) / float64(count+1) |
|
|
|
count += 1 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if r.Relative { |
|
|
@ -188,7 +249,7 @@ func (r *SceneRole) ApplyEffect(device *Device, c SceneRunContext) (newState New |
|
|
|
case SPDevice: |
|
|
|
newState.Power = nil |
|
|
|
case SPScene: |
|
|
|
// Do nothing
|
|
|
|
// Do nothing
|
|
|
|
case SPBoth: |
|
|
|
if newState.Power != nil { |
|
|
|
powerIntersection := *newState.Power && device.State.Power |
|
|
|