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.
 
 
 
 

121 lines
2.8 KiB

package models
import (
"context"
"regexp"
"strconv"
"strings"
)
type EventHandler struct {
ID int `json:"id"`
EventName string `json:"eventName"`
Conditions map[string]EventCondition `json:"conditions"`
TargetKind ReferenceKind `json:"targetType"`
TargetValue string `json:"targetValue"`
}
type EventHandlerRepository interface {
FindByID(ctx context.Context, id int) (EventHandler, error)
FetchAll(ctx context.Context) ([]EventHandler, error)
Save(ctx context.Context, handler *EventHandler)
Delete(ctx context.Context, handler *EventHandler)
}
type EventCondition struct {
EQ string `json:"eq,omitempty"`
GT string `json:"gt,omitempty"`
GTE string `json:"gte,omitempty"`
LT string `json:"lt,omitempty"`
LTE string `json:"lte,omitempty"`
}
func (h *EventHandler) MatchesEvent(event Event, targets []Device) bool {
if event.Name != h.EventName {
return false
}
for key, condition := range h.Conditions {
if !event.HasPayload(key) {
return false
}
if !condition.check(key, event.Payload[key], targets) {
return false
}
}
return true
}
func (c *EventCondition) check(key, value string, targets []Device) bool {
any := strings.Index(key, "any.") == 0
all := strings.Index(key, "all.") == 0
if any || all && len(key) > 4 {
count := 0
for _, target := range targets {
if c.checkDevice(key[4:], target) {
count++
}
}
return (any && count > 0) || (all && count == len(targets))
}
return c.matches(value)
}
func (c *EventCondition) checkDevice(key string, device Device) bool {
switch key {
case "power":
return c.matches(strconv.FormatBool(device.State.Power))
case "color":
return c.matches(device.State.Color.String())
case "intensity":
return c.matches(strconv.Itoa(device.State.Intensity))
case "temperature":
return c.matches(strconv.Itoa(device.State.Temperature))
}
return false
}
var numRegex = regexp.MustCompile("^{-[0-9].}+$")
func (c *EventCondition) matches(value string) bool {
if numRegex.MatchString(value) {
numValue, _ := strconv.ParseFloat(c.LT, 64)
stillAlive := true
if c.LT != "" {
lt, _ := strconv.ParseFloat(c.LT, 64)
stillAlive = numValue < lt
}
if stillAlive && c.LTE != "" {
lte, _ := strconv.ParseFloat(c.LTE, 64)
stillAlive = numValue <= lte
}
if stillAlive && c.EQ != "" {
eq, _ := strconv.ParseFloat(c.EQ, 64)
stillAlive = numValue == eq
}
if stillAlive && c.GTE != "" {
gte, _ := strconv.ParseFloat(c.GTE, 64)
stillAlive = numValue == gte
}
if stillAlive && c.GT != "" {
gt, _ := strconv.ParseFloat(c.GT, 64)
stillAlive = numValue > gt
}
return stillAlive
} else if c.EQ != "" {
return strings.ToLower(c.EQ) == strings.ToLower(value)
} else {
return false
}
}