Browse Source

change presence events, fix non-eq conditions.

feature-colorvalue2
Gisle Aune 3 years ago
parent
commit
ad2f912a6f
  1. 7
      internal/drivers/hue/bridge.go
  2. 38
      internal/drivers/hue/state.go
  3. 6
      models/eventhandler.go
  4. 2
      models/timeofday.go
  5. 40
      models/timeofday_test.go

7
internal/drivers/hue/bridge.go

@ -76,9 +76,10 @@ func (b *Bridge) Refresh(ctx context.Context) error {
if state == nil { if state == nil {
state = &hueSensorState{ state = &hueSensorState{
index: index,
uniqueID: sensor.UniqueID,
externalID: -1,
index: index,
uniqueID: sensor.UniqueID,
externalID: -1,
presenceCooldown: -2,
} }
b.sensorStates = append(b.sensorStates, state) b.sensorStates = append(b.sensorStates, state)

38
internal/drivers/hue/state.go

@ -92,7 +92,7 @@ type hueSensorState struct {
uniqueID string uniqueID string
prevData *SensorData prevData *SensorData
prevTime time.Time prevTime time.Time
presenceCooldown bool
presenceCooldown int
} }
func (state *hueSensorState) Update(newData SensorData) *models.Event { func (state *hueSensorState) Update(newData SensorData) *models.Event {
@ -153,26 +153,36 @@ func (state *hueSensorState) Update(newData SensorData) *models.Event {
case "ZLLPresence": case "ZLLPresence":
{ {
if state.prevData != nil && state.prevData.State.Presence != newData.State.Presence { if state.prevData != nil && state.prevData.State.Presence != newData.State.Presence {
name := models.ENSensorPresenceStarted
if !newData.State.Presence {
name = models.ENSensorPresenceEnding
state.presenceCooldown = true
if newData.State.Presence {
state.presenceCooldown = -1
return &models.Event{
Name: models.ENSensorPresenceStarted,
Payload: map[string]string{
"deviceId": strconv.Itoa(state.externalID),
"deviceInternalId": newData.UniqueID,
},
}
} else {
state.presenceCooldown = 0
} }
}
if state.presenceCooldown == -2 {
state.presenceCooldown = int(time.Since(stateTime) / time.Minute)
}
nextEventWait := time.Minute * time.Duration(state.presenceCooldown)
if state.presenceCooldown != -1 && !newData.State.Presence && time.Since(stateTime) > nextEventWait {
state.presenceCooldown += 1
return &models.Event{
Name: name,
Payload: map[string]string{
"deviceId": strconv.Itoa(state.externalID),
"deviceInternalId": newData.UniqueID,
},
}
} else if state.presenceCooldown && !newData.State.Presence && time.Since(stateTime) > time.Minute {
state.presenceCooldown = false
return &models.Event{ return &models.Event{
Name: models.ENSensorPresenceEnded, Name: models.ENSensorPresenceEnded,
Payload: map[string]string{ Payload: map[string]string{
"deviceId": strconv.Itoa(state.externalID), "deviceId": strconv.Itoa(state.externalID),
"deviceInternalId": newData.UniqueID, "deviceInternalId": newData.UniqueID,
"minutesElapsed": strconv.Itoa(state.presenceCooldown - 1),
"secondsElapsed": strconv.Itoa((state.presenceCooldown - 1) * 60),
}, },
} }
} }

6
models/eventhandler.go

@ -173,11 +173,11 @@ func (c *EventCondition) checkDevice(key string, device Device) (matches bool, s
} }
} }
var numRegex = regexp.MustCompile("^{-[0-9].}+$")
var numRegex = regexp.MustCompile("^-*[0-9]+(.[0-9]+)*$")
func (c *EventCondition) matches(value string) bool { func (c *EventCondition) matches(value string) bool {
if numRegex.MatchString(value) { if numRegex.MatchString(value) {
numValue, _ := strconv.ParseFloat(c.LT, 64)
numValue, _ := strconv.ParseFloat(value, 64)
stillAlive := true stillAlive := true
if c.LT != "" { if c.LT != "" {
@ -197,7 +197,7 @@ func (c *EventCondition) matches(value string) bool {
if stillAlive && c.GTE != "" { if stillAlive && c.GTE != "" {
gte, _ := strconv.ParseFloat(c.GTE, 64) gte, _ := strconv.ParseFloat(c.GTE, 64)
stillAlive = numValue == gte
stillAlive = numValue >= gte
} }
if stillAlive && c.GT != "" { if stillAlive && c.GT != "" {

2
models/timeofday.go

@ -75,7 +75,7 @@ func (t TimeOfDay) IsBetween(from TimeOfDay, to TimeOfDay) bool {
if from == to { if from == to {
return t == from return t == from
} else if from > to { } else if from > to {
return t >= to || t <= from
return t >= from || t <= to
} else { } else {
return t >= from && t <= to return t >= from && t <= to
} }

40
models/timeofday_test.go

@ -0,0 +1,40 @@
package models
import (
"fmt"
"testing"
)
func tod(s string) TimeOfDay {
tod, err := ParseTimeOfDay(s)
if err != nil {
panic(err)
}
return tod
}
func TestTimeOfDay_IsBetween(t *testing.T) {
table := []struct{
Value TimeOfDay
From TimeOfDay
To TimeOfDay
Expected bool
}{
{ tod("16:13:11"), tod("07"), tod("21:30"), true },
{ tod("16:13:31"), tod("21:30"), tod("07"), false },
{ tod("23:15:32"), tod("21:30"), tod("07"), true },
{ tod("04:13:57"), tod("21:30"), tod("07"), true },
{ tod("16:14:43"), tod("15:30"), tod("16:00"), false },
{ tod("16:14:43"), tod("15:30"), tod("16:15"), true },
}
for i, row := range table {
t.Run(fmt.Sprintf("row_%d", i), func (t *testing.T) {
if row.Value.IsBetween(row.From, row.To) != row.Expected {
t.Log(row.Value, row.From, row.To)
t.Fail()
}
})
}
}
Loading…
Cancel
Save